Repository: apache/streampipes
Pull request #3229 (2024-09-16 10:45:39)

chore(deps): bump body-parser and express in /ui
Bumps [body-parser](https://github.com/expressjs/body-parser) and [express](https://github.com/expressjs/express). These dependencies needed to be updated together.
Updates `body-parser` from 1.20.2 to 1.20.3
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/expressjs/body-parser/releases">body-parser's releases</a>.</em></p>
<blockquote>
<h2>1.20.3</h2>
<h2>What's Changed</h2>
<h3>Important</h3>
<ul>
<li>deps: qs@6.13.0</li>
<li>add <code>depth</code> option to customize the depth level in the parser</li>
<li><strong>IMPORTANT:</strong> The default <code>depth</code> level for parsing URL-encoded data is now <code>32</code> (previously was <code>Infinity</code>). <a href="https://github.com/expressjs/body-parser/blob/17529513673e39ba79886a7ce3363320cf1c0c50/README.md#depth">Documentation</a></li>
</ul>
<h3>Other changes</h3>
<ul>
<li>chore: add support for OSSF scorecard reporting by <a href="https://github.com/inigomarquinez"><code>@​inigomarquinez</code></a> in <a href="https://redirect.github.com/expressjs/body-parser/pull/522">expressjs/body-parser#522</a></li>
<li>ci: fix errors in ci github action for node 8 and 9 by <a href="https://github.com/inigomarquinez"><code>@​inigomarquinez</code></a> in <a href="https://redirect.github.com/expressjs/body-parser/pull/523">expressjs/body-parser#523</a></li>
<li>fix: pin to node@22.4.1 by <a href="https://github.com/wesleytodd"><code>@​wesleytodd</code></a> in <a href="https://redirect.github.com/expressjs/body-parser/pull/527">expressjs/body-parser#527</a></li>
<li>deps: qs@6.12.3 by <a href="https://github.com/melikhov-dev"><code>@​melikhov-dev</code></a> in <a href="https://redirect.github.com/expressjs/body-parser/pull/521">expressjs/body-parser#521</a></li>
<li>Add OSSF Scorecard badge by <a href="https://github.com/bjohansebas"><code>@​bjohansebas</code></a> in <a href="https://redirect.github.com/expressjs/body-parser/pull/531">expressjs/body-parser#531</a></li>
<li>Linter by <a href="https://github.com/UlisesGascon"><code>@​UlisesGascon</code></a> in <a href="https://redirect.github.com/expressjs/body-parser/pull/534">expressjs/body-parser#534</a></li>
<li>Release: 1.20.3 by <a href="https://github.com/UlisesGascon"><code>@​UlisesGascon</code></a> in <a href="https://redirect.github.com/expressjs/body-parser/pull/535">expressjs/body-parser#535</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/inigomarquinez"><code>@​inigomarquinez</code></a> made their first contribution in <a href="https://redirect.github.com/expressjs/body-parser/pull/522">expressjs/body-parser#522</a></li>
<li><a href="https://github.com/melikhov-dev"><code>@​melikhov-dev</code></a> made their first contribution in <a href="https://redirect.github.com/expressjs/body-parser/pull/521">expressjs/body-parser#521</a></li>
<li><a href="https://github.com/bjohansebas"><code>@​bjohansebas</code></a> made their first contribution in <a href="https://redirect.github.com/expressjs/body-parser/pull/531">expressjs/body-parser#531</a></li>
<li><a href="https://github.com/UlisesGascon"><code>@​UlisesGascon</code></a> made their first contribution in <a href="https://redirect.github.com/expressjs/body-parser/pull/534">expressjs/body-parser#534</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a href="https://github.com/expressjs/body-parser/compare/1.20.2...1.20.3">https://github.com/expressjs/body-parser/compare/1.20.2...1.20.3</a></p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a href="https://github.com/expressjs/body-parser/blob/master/HISTORY.md">body-parser's changelog</a>.</em></p>
<blockquote>
<h1>1.20.3 / 2024-09-10</h1>
<ul>
<li>deps: qs@6.13.0</li>
<li>add <code>depth</code> option to customize the depth level in the parser</li>
<li>IMPORTANT: The default <code>depth</code> level for parsing URL-encoded data is now <code>32</code> (previously was <code>Infinity</code>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/expressjs/body-parser/commit/17529513673e39ba79886a7ce3363320cf1c0c50"><code>1752951</code></a> 1.20.3</li>
<li><a href="https://github.com/expressjs/body-parser/commit/39744cfe2ac4fb37a19ed7c43e3a74332f428e17"><code>39744cf</code></a> chore: linter (<a href="https://redirect.github.com/expressjs/body-parser/issues/534">#534</a>)</li>
<li><a href="https://github.com/expressjs/body-parser/commit/b2695c4450f06ba3b0ccf48d872a229bb41c9bce"><code>b2695c4</code></a> Merge commit from fork</li>
<li><a href="https://github.com/expressjs/body-parser/commit/ade0f3f82f91086d6cd2ed2cb4b0aff448fbc2e5"><code>ade0f3f</code></a> add scorecard to readme (<a href="https://redirect.github.com/expressjs/body-parser/issues/531">#531</a>)</li>
<li><a href="https://github.com/expressjs/body-parser/commit/99a1bd62456f932004b84767d6393bc261f75d36"><code>99a1bd6</code></a> deps: qs@6.12.3 (<a href="https://redirect.github.com/expressjs/body-parser/issues/521">#521</a>)</li>
<li><a href="https://github.com/expressjs/body-parser/commit/947859160527c7aaaa20da79e2c3ba542baaaf66"><code>9478591</code></a> fix: pin to node@22.4.1</li>
<li><a href="https://github.com/expressjs/body-parser/commit/83db46a1e5512135ce01ed90b9132ee16a2657a8"><code>83db46a</code></a> ci: fix errors in ci github action for node 8 and 9 (<a href="https://redirect.github.com/expressjs/body-parser/issues/523">#523</a>)</li>
<li><a href="https://github.com/expressjs/body-parser/commit/9d4e2125b580b055b2a3aa140df9b8fce363af46"><code>9d4e212</code></a> chore: add support for OSSF scorecard reporting (<a href="https://redirect.github.com/expressjs/body-parser/issues/522">#522</a>)</li>
<li>See full diff in <a href="https://github.com/expressjs/body-parser/compare/1.20.2...1.20.3">compare view</a></li>
</ul>
</details>
<details>
<summary>Maintainer changes</summary>
<p>This version was pushed to npm by <a href="https://www.npmjs.com/~ulisesgascon">ulisesgascon</a>, a new releaser for body-parser since your current version.</p>
</details>
<br />

Updates `express` from 4.19.2 to 4.21.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/expressjs/express/releases">express's releases</a>.</em></p>
<blockquote>
<h2>4.21.0</h2>
<h2>What's Changed</h2>
<ul>
<li>Deprecate <code>&quot;back&quot;</code> magic string in redirects by <a href="https://github.com/blakeembrey"><code>@​blakeembrey</code></a> in <a href="https://redirect.github.com/expressjs/express/pull/5935">expressjs/express#5935</a></li>
<li>finalhandler@1.3.1 by <a href="https://github.com/wesleytodd"><code>@​wesleytodd</code></a> in <a href="https://redirect.github.com/expressjs/express/pull/5954">expressjs/express#5954</a></li>
<li>fix(deps): serve-static@1.16.2 by <a href="https://github.com/wesleytodd"><code>@​wesleytodd</code></a> in <a href="https://redirect.github.com/expressjs/express/pull/5951">expressjs/express#5951</a></li>
<li>Upgraded dependency qs to 6.13.0 to match qs in body-parser by <a href="https://github.com/agadzinski93"><code>@​agadzinski93</code></a> in <a href="https://redirect.github.com/expressjs/express/pull/5946">expressjs/express#5946</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/agadzinski93"><code>@​agadzinski93</code></a> made their first contribution in <a href="https://redirect.github.com/expressjs/express/pull/5946">expressjs/express#5946</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a href="https://github.com/expressjs/express/compare/4.20.0...4.21.0">https://github.com/expressjs/express/compare/4.20.0...4.21.0</a></p>
<h2>4.20.0</h2>
<h2>What's Changed</h2>
<h3>Important</h3>
<ul>
<li>IMPORTANT: The default <code>depth</code> level for parsing URL-encoded data is now <code>32</code> (previously was <code>Infinity</code>)</li>
<li>Remove link renderization in html while using <code>res.redirect</code></li>
</ul>
<h3>Other Changes</h3>
<ul>
<li>4.19.2 Staging by <a href="https://github.com/wesleytodd"><code>@​wesleytodd</code></a> in <a href="https://redirect.github.com/expressjs/express/pull/5561">expressjs/express#5561</a></li>
<li>remove duplicate location test for data uri by <a href="https://github.com/wesleytodd"><code>@​wesleytodd</code></a> in <a href="https://redirect.github.com/expressjs/express/pull/5562">expressjs/express#5562</a></li>
<li>feat: document beta releases expectations by <a href="https://github.com/marco-ippolito"><code>@​marco-ippolito</code></a> in <a href="https://redirect.github.com/expressjs/express/pull/5565">expressjs/express#5565</a></li>
<li>Cut down on duplicated CI runs by <a href="https://github.com/jonchurch"><code>@​jonchurch</code></a> in <a href="https://redirect.github.com/expressjs/express/pull/5564">expressjs/express#5564</a></li>
<li>Add a Threat Model by <a href="https://github.com/UlisesGascon"><code>@​UlisesGascon</code></a> in <a href="https://redirect.github.com/expressjs/express/pull/5526">expressjs/express#5526</a></li>
<li>Assign captain of encodeurl by <a href="https://github.com/blakeembrey"><code>@​blakeembrey</code></a> in <a href="https://redirect.github.com/expressjs/express/pull/5579">expressjs/express#5579</a></li>
<li>Nominate jonchurch as repo captain for <code>http-errors</code>, <code>expressjs.com</code>, <code>morgan</code>, <code>cors</code>, <code>body-parser</code> by <a href="https://github.com/jonchurch"><code>@​jonchurch</code></a> in <a href="https://redirect.github.com/expressjs/express/pull/5587">expressjs/express#5587</a></li>
<li>docs: update Security.md by <a href="https://github.com/inigomarquinez"><code>@​inigomarquinez</code></a> in <a href="https://redirect.github.com/expressjs/express/pull/5590">expressjs/express#5590</a></li>
<li>docs: update triage nomination policy by <a href="https://github.com/UlisesGascon"><code>@​UlisesGascon</code></a> in <a href="https://redirect.github.com/expressjs/express/pull/5600">expressjs/express#5600</a></li>
<li>Add CodeQL (SAST) by <a href="https://github.com/UlisesGascon"><code>@​UlisesGascon</code></a> in <a href="https://redirect.github.com/expressjs/express/pull/5433">expressjs/express#5433</a></li>
<li>docs: add UlisesGascon as triage initiative captain by <a href="https://github.com/UlisesGascon"><code>@​UlisesGascon</code></a> in <a href="https://redirect.github.com/expressjs/express/pull/5605">expressjs/express#5605</a></li>
<li>deps: encodeurl@~2.0.0 by <a href="https://github.com/blakeembrey"><code>@​blakeembrey</code></a> in <a href="https://redirect.github.com/expressjs/express/pull/5569">expressjs/express#5569</a></li>
<li>skip QUERY method test by <a href="https://github.com/jonchurch"><code>@​jonchurch</code></a> in <a href="https://redirect.github.com/expressjs/express/pull/5628">expressjs/express#5628</a></li>
<li>ignore ETAG query test on 21 and 22, reuse skip util by <a href="https://github.com/jonchurch"><code>@​jonchurch</code></a> in <a href="https://redirect.github.com/expressjs/express/pull/5639">expressjs/express#5639</a></li>
<li>add support Node.js@22 in the CI by <a href="https://github.com/mertcanaltin"><code>@​mertcanaltin</code></a> in <a href="https://redirect.github.com/expressjs/express/pull/5627">expressjs/express#5627</a></li>
<li>doc: add table of contents, tc/triager lists to readme by <a href="https://github.com/mertcanaltin"><code>@​mertcanaltin</code></a> in <a href="https://redirect.github.com/expressjs/express/pull/5619">expressjs/express#5619</a></li>
<li>List and sort all projects, add captains by <a href="https://github.com/blakeembrey"><code>@​blakeembrey</code></a> in <a href="https://redirect.github.com/expressjs/express/pull/5653">expressjs/express#5653</a></li>
<li>docs: add <a href="https://github.com/UlisesGascon"><code>@​UlisesGascon</code></a> as captain for cookie-parser by <a href="https://github.com/UlisesGascon"><code>@​UlisesGascon</code></a> in <a href="https://redirect.github.com/expressjs/express/pull/5666">expressjs/express#5666</a></li>
<li>✨ bring back query tests for node 21 by <a href="https://github.com/ctcpip"><code>@​ctcpip</code></a> in <a href="https://redirect.github.com/expressjs/express/pull/5690">expressjs/express#5690</a></li>
<li>[v4] Deprecate <code>res.clearCookie</code> accepting <code>options.maxAge</code> and <code>options.expires</code> by <a href="https://github.com/jonchurch"><code>@​jonchurch</code></a> in <a href="https://redirect.github.com/expressjs/express/pull/5672">expressjs/express#5672</a></li>
<li>skip QUERY tests for Node 21 only, still not supported by <a href="https://github.com/jonchurch"><code>@​jonchurch</code></a> in <a href="https://redirect.github.com/expressjs/express/pull/5695">expressjs/express#5695</a></li>
<li>📝 update people, add ctcpip to TC by <a href="https://github.com/ctcpip"><code>@​ctcpip</code></a> in <a href="https://redirect.github.com/expressjs/express/pull/5683">expressjs/express#5683</a></li>
<li>remove minor version pinning from ci by <a href="https://github.com/jonchurch"><code>@​jonchurch</code></a> in <a href="https://redirect.github.com/expressjs/express/pull/5722">expressjs/express#5722</a></li>
<li>Fix link variable use in attribution section of CODE OF CONDUCT by <a href="https://github.com/IamLizu"><code>@​IamLizu</code></a> in <a href="https://redirect.github.com/expressjs/express/pull/5762">expressjs/express#5762</a></li>
<li>Replace Appveyor windows testing with GHA by <a href="https://github.com/jonchurch"><code>@​jonchurch</code></a> in <a href="https://redirect.github.com/expressjs/express/pull/5599">expressjs/express#5599</a></li>
<li>Add OSSF Scorecard badge by <a href="https://github.com/UlisesGascon"><code>@​UlisesGascon</code></a> in <a href="https://redirect.github.com/expressjs/express/pull/5436">expressjs/express#5436</a></li>
<li>update scorecard link by <a href="https://github.com/bjohansebas"><code>@​bjohansebas</code></a> in <a href="https://redirect.github.com/expressjs/express/pull/5814">expressjs/express#5814</a></li>
<li>Nominate <a href="https://github.com/IamLizu"><code>@​IamLizu</code></a> to the triage team by <a href="https://github.com/UlisesGascon"><code>@​UlisesGascon</code></a> in <a href="https://redirect.github.com/expressjs/express/pull/5836">expressjs/express#5836</a></li>
<li>deps: path-to-regexp@0.1.8 by <a href="https://github.com/blakeembrey"><code>@​blakeembrey</code></a> in <a href="https://redirect.github.com/expressjs/express/pull/5603">expressjs/express#5603</a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a href="https://github.com/expressjs/express/blob/4.21.0/History.md">express's changelog</a>.</em></p>
<blockquote>
<h1>4.21.0 / 2024-09-11</h1>
<ul>
<li>Deprecate <code>res.location(&quot;back&quot;)</code> and <code>res.redirect(&quot;back&quot;)</code> magic string</li>
<li>deps: serve-static@1.16.2
<ul>
<li>includes send@0.19.0</li>
</ul>
</li>
<li>deps: finalhandler@1.3.1</li>
<li>deps: qs@6.13.0</li>
</ul>
<h1>4.20.0 / 2024-09-10</h1>
<ul>
<li>deps: serve-static@0.16.0
<ul>
<li>Remove link renderization in html while redirecting</li>
</ul>
</li>
<li>deps: send@0.19.0
<ul>
<li>Remove link renderization in html while redirecting</li>
</ul>
</li>
<li>deps: body-parser@0.6.0
<ul>
<li>add <code>depth</code> option to customize the depth level in the parser</li>
<li>IMPORTANT: The default <code>depth</code> level for parsing URL-encoded data is now <code>32</code> (previously was <code>Infinity</code>)</li>
</ul>
</li>
<li>Remove link renderization in html while using <code>res.redirect</code></li>
<li>deps: path-to-regexp@0.1.10
<ul>
<li>Adds support for named matching groups in the routes using a regex</li>
<li>Adds backtracking protection to parameters without regexes defined</li>
</ul>
</li>
<li>deps: encodeurl@~2.0.0
<ul>
<li>Removes encoding of <code>\</code>, <code>|</code>, and <code>^</code> to align better with URL spec</li>
</ul>
</li>
<li>Deprecate passing <code>options.maxAge</code> and <code>options.expires</code> to <code>res.clearCookie</code>
<ul>
<li>Will be ignored in v5, clearCookie will set a cookie with an expires in the past to instruct clients to delete the cookie</li>
</ul>
</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/expressjs/express/commit/7e562c6d8daddff4604f8efaaf9db2cf98c6dcff"><code>7e562c6</code></a> 4.21.0</li>
<li><a href="https://github.com/expressjs/express/commit/1bcde96bc87c4704df9a704271d1167064ab56bb"><code>1bcde96</code></a> fix(deps): qs@6.13.0 (<a href="https://redirect.github.com/expressjs/express/issues/5946">#5946</a>)</li>
<li><a href="https://github.com/expressjs/express/commit/7d364775688be98aaa973302e066d0da9f438997"><code>7d36477</code></a> fix(deps): serve-static@1.16.2 (<a href="https://redirect.github.com/expressjs/express/issues/5951">#5951</a>)</li>
<li><a href="https://github.com/expressjs/express/commit/40d2d8f2c882712a0f2e4603c38d166c79676b2b"><code>40d2d8f</code></a> fix(deps): finalhandler@1.3.1</li>
<li><a href="https://github.com/expressjs/express/commit/77ada906dba57fd6e308f0d750e01653dbeaddfc"><code>77ada90</code></a> Deprecate <code>&quot;back&quot;</code> magic string in redirects (<a href="https://redirect.github.com/expressjs/express/issues/5935">#5935</a>)</li>
<li><a href="https://github.com/expressjs/express/commit/21df421ebc7a5249bb31101da666bbf22adc3f18"><code>21df421</code></a> 4.20.0</li>
<li><a href="https://github.com/expressjs/express/commit/4c9ddc1c47bf579e55c2fe837d76a952e9fd8959"><code>4c9ddc1</code></a> feat: upgrade to serve-static@0.16.0</li>
<li><a href="https://github.com/expressjs/express/commit/9ebe5d500d22cbb2b8aaa73446866b084c747971"><code>9ebe5d5</code></a> feat: upgrade to send@0.19.0 (<a href="https://redirect.github.com/expressjs/express/issues/5928">#5928</a>)</li>
<li><a href="https://github.com/expressjs/express/commit/ec4a01b6b8814d7b007f36a3023f4dbafdbc3d09"><code>ec4a01b</code></a> feat: upgrade to body-parser@1.20.3 (<a href="https://redirect.github.com/expressjs/express/issues/5926">#5926</a>)</li>
<li><a href="https://github.com/expressjs/express/commit/54271f69b511fea198471e6ff3400ab805d6b553"><code>54271f6</code></a> fix: don't render redirect values in anchor href</li>
<li>Additional commits viewable in <a href="https://github.com/expressjs/express/compare/4.19.2...4.21.0">compare view</a></li>
</ul>
</details>
<br />


Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/apache/streampipes/network/alerts).

</details>


Patch:
diff --git a/.github/workflows/osv-scanner.yml b/.github/workflows/osv-scanner.yml
index 7c1a2e231c..0d006f3c29 100644
--- a/.github/workflows/osv-scanner.yml
+++ b/.github/workflows/osv-scanner.yml
@@ -40,7 +40,7 @@ jobs:
 
       - name: Create Pull Request
         id: cpr
-        uses: peter-evans/create-pull-request@v6
+        uses: peter-evans/create-pull-request@v7
         with:
           token: ${{ secrets.GITHUB_TOKEN }}
           committer: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
diff --git a/installer/k8s/README.md b/installer/k8s/README.md
index 598e034ce9..48afd5a59e 100644
--- a/installer/k8s/README.md
+++ b/installer/k8s/README.md
@@ -78,8 +78,7 @@ ui-b94bd9766-rm6zb                             2/2     Running   0          3m27
 For **minikube users**:
 > **NOTE**: If you're running Docker Desktop or Minikube with a local k8s cluster, the above step to use your host IP
 > might not work. Luckily, you can port-forward a service port to your localhost using the following command to be able to
-> access the UI either via `http://localhost` or `http://<HOST_IP>` (you require sudo to run this command in order to bind
-> to a privileged port).
+> access the UI either via `http://localhost:8088` or `http://<HOST_IP>:8088` (If you want to use privileged ports such as 80, you need to run this command with sudo to bind to the privileged port).
 
 ```bash
 kubectl port-forward svc/ui --address=0.0.0.0 8088:8088
diff --git a/pom.xml b/pom.xml
index b5b52c3d1a..0eb677e528 100644
--- a/pom.xml
+++ b/pom.xml
@@ -105,7 +105,7 @@
         <plexus-interactivity-api.version>1.1</plexus-interactivity-api.version>
         <plexus-utils.version>4.0.0</plexus-utils.version>
         <postgresql.version>42.7.2</postgresql.version>
-        <protobuf.version>4.27.0</protobuf.version>
+        <protobuf.version>4.28.2</protobuf.version>
         <pulsar.version>3.2.2</pulsar.version>
         <quartz.version>2.3.2</quartz.version>
         <!-- needs to be lower than 4.x.x, see https://github.com/apache/streampipes/issues/1495 -->
diff --git a/streampipes-client-go/streampipes/model/common.go b/streampipes-client-go/streampipes/model/common.go
index 0cb1d9631f..d5a81d684b 100644
--- a/streampipes-client-go/streampipes/model/common.go
+++ b/streampipes-client-go/streampipes/model/common.go
@@ -29,7 +29,7 @@ type EventProperty struct {
 	Label              string             `json:"label,omitempty"`
 	Description        string             `json:"description,omitempty"`
 	RuntimeName        string             `json:"runtimeName,omitempty"`
-	DomainProperties   []string           `json:"domainProperties,omitempty"`
+	SemanticType       string             `json:"semanticType,omitempty"`
 	PropertyScope      string             `json:"propertyScope,omitempty"`
 	RuntimeID          string             `json:"runtimeId,omitempty"`
 	RuntimeType        string             `json:"runtimeType"`
@@ -42,7 +42,7 @@ type EventProperties struct {
 	Label              string            `json:"label"`
 	Description        string            `json:"description"`
 	RuntimeName        string            `json:"runtimeName"`
-	DomainProperties   []string          `json:"domainProperties"`
+	SemanticType       string            `json:"semanticType"`
 	PropertyScope      string            `json:"propertyScope"`
 	RuntimeID          string            `json:"runtimeId"`
 	RuntimeType        string            `json:"runtimeType,omitempty"`
diff --git a/streampipes-client-python/.pre-commit-config.yaml b/streampipes-client-python/.pre-commit-config.yaml
index 04ccf3070c..e9ac86e307 100644
--- a/streampipes-client-python/.pre-commit-config.yaml
+++ b/streampipes-client-python/.pre-commit-config.yaml
@@ -14,7 +14,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
-files: streampipes/|tests/
+files: ^streampipes-client-python/(streampipes|tests)/
 repos:
   - repo: https://github.com/pre-commit/pre-commit-hooks
     rev: v4.6.0
diff --git a/streampipes-client-python/streampipes/functions/utils/data_stream_generator.py b/streampipes-client-python/streampipes/functions/utils/data_stream_generator.py
index 6d042088f3..6587a2e53c 100644
--- a/streampipes-client-python/streampipes/functions/utils/data_stream_generator.py
+++ b/streampipes-client-python/streampipes/functions/utils/data_stream_generator.py
@@ -78,7 +78,7 @@ def create_data_stream(
             EventProperty(  # type: ignore
                 label="timestamp",
                 runtime_name="timestamp",
-                domain_properties=["http://schema.org/DateTime"],
+                semantic_type="http://schema.org/DateTime",
                 property_scope="HEADER_PROPERTY",
                 runtime_type="http://www.w3.org/2001/XMLSchema#long",
             )
diff --git a/streampipes-client-python/streampipes/model/common.py b/streampipes-client-python/streampipes/model/common.py
index 950bb7f066..afcac4beac 100644
--- a/streampipes-client-python/streampipes/model/common.py
+++ b/streampipes-client-python/streampipes/model/common.py
@@ -109,7 +109,7 @@ class EventProperty(BasicModel):
     label: Optional[StrictStr]
     description: Optional[StrictStr]
     runtime_name: StrictStr
-    domain_properties: Optional[List[StrictStr]] = Field(default_factory=list)
+    semantic_type: Optional[StrictStr]
     property_scope: Optional[StrictStr] = Field(default="MEASUREMENT_PROPERTY")
     runtime_id: Optional[StrictStr]
     runtime_type: StrictStr = Field(default="http://www.w3.org/2001/XMLSchema#string")
diff --git a/streampipes-connect-management/src/main/java/org/apache/streampipes/connect/management/compact/PersistPipelineHandler.java b/streampipes-connect-management/src/main/java/org/apache/streampipes/connect/management/compact/PersistPipelineHandler.java
index f385334d05..7a262fca26 100644
--- a/streampipes-connect-management/src/main/java/org/apache/streampipes/connect/management/compact/PersistPipelineHandler.java
+++ b/streampipes-connect-management/src/main/java/org/apache/streampipes/connect/management/compact/PersistPipelineHandler.java
@@ -29,9 +29,6 @@ import org.apache.streampipes.model.staticproperty.OneOfStaticProperty;
 import org.apache.streampipes.model.template.PipelineTemplateInvocation;
 import org.apache.streampipes.vocabulary.SO;
 
-import java.net.URI;
-import java.util.List;
-
 public class PersistPipelineHandler {
 
   private static final String templateId = "org.apache.streampipes.manager.template.instances.DataLakePipelineTemplate";
@@ -97,16 +94,13 @@ public class PersistPipelineHandler {
         .stream()
         .filter(ep -> ep instanceof EventPropertyPrimitive)
         .map(ep -> (EventPropertyPrimitive) ep)
-        .filter(ep -> hasTimestampType(ep.getDomainProperties()))
+        .filter(ep -> hasTimestampType(ep.getSemanticType()))
         .map(EventProperty::getRuntimeName)
         .findFirst()
         .orElseThrow(() -> new IllegalArgumentException("Could not find timestamp field in schema"));
   }
 
-  private boolean hasTimestampType(List<URI> semanticTypes) {
-    return semanticTypes
-        .stream()
-        .map(URI::toString)
-        .anyMatch(s -> s.equalsIgnoreCase(SO.DATE_TIME));
+  private boolean hasTimestampType(String semanticType) {
+    return SO.DATE_TIME.equalsIgnoreCase(semanticType);
   }
 }
diff --git a/streampipes-connect-management/src/main/java/org/apache/streampipes/connect/management/compact/SchemaMetadataEnricher.java b/streampipes-connect-management/src/main/java/org/apache/streampipes/connect/management/compact/SchemaMetadataEnricher.java
index 1650839226..bc2a2ffba0 100644
--- a/streampipes-connect-management/src/main/java/org/apache/streampipes/connect/management/compact/SchemaMetadataEnricher.java
+++ b/streampipes-connect-management/src/main/java/org/apache/streampipes/connect/management/compact/SchemaMetadataEnricher.java
@@ -24,9 +24,6 @@ import org.apache.streampipes.model.schema.EventPropertyPrimitive;
 import org.apache.streampipes.model.schema.PropertyScope;
 import org.apache.streampipes.vocabulary.XSD;
 
-import java.net.URI;
-import java.util.List;
-
 public class SchemaMetadataEnricher {
 
   public void enrich(EventProperty property,
@@ -41,7 +38,7 @@ public class SchemaMetadataEnricher {
       property.setDescription(propertyDef.description());
     }
     if (property instanceof EventPropertyPrimitive && propertyDef.semanticType() != null) {
-      property.setDomainProperties(List.of(URI.create(propertyDef.semanticType())));
+      property.setSemanticType(propertyDef.semanticType());
     }
   }
 
diff --git a/streampipes-connect-shared/src/main/java/org/apache/streampipes/connect/shared/preprocessing/convert/ToOriginalSchemaConverter.java b/streampipes-connect-shared/src/main/java/org/apache/streampipes/connect/shared/preprocessing/convert/ToOriginalSchemaConverter.java
index a7ff90b45c..8e2381d506 100644
--- a/streampipes-connect-shared/src/main/java/org/apache/streampipes/connect/shared/preprocessing/convert/ToOriginalSchemaConverter.java
+++ b/streampipes-connect-shared/src/main/java/org/apache/streampipes/connect/shared/preprocessing/convert/ToOriginalSchemaConverter.java
@@ -125,7 +125,7 @@ public class ToOriginalSchemaConverter implements ITransformationRuleVisitor, Pr
   public void visit(TimestampTranfsformationRuleDescription rule) {
     var property = findPrimitiveProperty(properties, rule.getRuntimeKey());
     property.setRuntimeType(Datatypes.String.toString());
-    property.setDomainProperties(List.of());
+    property.setSemanticType(null);
   }
 
   @Override
diff --git a/streampipes-connect-shared/src/main/java/org/apache/streampipes/connect/shared/preprocessing/convert/ToTransformedSchemaConverter.java b/streampipes-connect-shared/src/main/java/org/apache/streampipes/connect/shared/preprocessing/convert/ToTransformedSchemaConverter.java
index 92b1674d0d..8ea159406f 100644
--- a/streampipes-connect-shared/src/main/java/org/apache/streampipes/connect/shared/preprocessing/convert/ToTransformedSchemaConverter.java
+++ b/streampipes-connect-shared/src/main/java/org/apache/streampipes/connect/shared/preprocessing/convert/ToTransformedSchemaConverter.java
@@ -127,7 +127,7 @@ public class ToTransformedSchemaConverter implements ITransformationRuleVisitor,
     property.setPropertyScope(rule.getPropertyScope().name());
 
     if (Objects.nonNull(rule.getSemanticType())) {
-      property.setDomainProperties(List.of(URI.create(rule.getSemanticType())));
+      property.setSemanticType(rule.getSemanticType());
     }
     if (Objects.nonNull(rule.getMeasurementUnit())) {
       property.setMeasurementUnit(URI.create(rule.getMeasurementUnit()));
@@ -152,7 +152,7 @@ public class ToTransformedSchemaConverter implements ITransformationRuleVisitor,
   @Override
   public void visit(TimestampTranfsformationRuleDescription rule) {
     var property = findPrimitiveProperty(properties, rule.getRuntimeKey());
-    property.setDomainProperties(List.of(URI.create("http://schema.org/DateTime")));
+    property.setSemanticType("http://schema.org/DateTime");
     property.setRuntimeType(Datatypes.Long.toString());
     property.setPropertyScope(PropertyScope.HEADER_PROPERTY.toString());
     var metadata = property.getAdditionalMetadata();
diff --git a/streampipes-data-explorer-api/src/main/java/org/apache/streampipes/dataexplorer/api/IDataExplorerManager.java b/streampipes-data-explorer-api/src/main/java/org/apache/streampipes/dataexplorer/api/IDataExplorerManager.java
index ef1b68a0ca..586a77706c 100644
--- a/streampipes-data-explorer-api/src/main/java/org/apache/streampipes/dataexplorer/api/IDataExplorerManager.java
+++ b/streampipes-data-explorer-api/src/main/java/org/apache/streampipes/dataexplorer/api/IDataExplorerManager.java
@@ -34,15 +34,19 @@ public interface IDataExplorerManager {
    * @return An instance of {@link IDataLakeMeasurementCounter} configured to count the sizes of the specified measurements.
    */
   IDataLakeMeasurementCounter getMeasurementCounter(
-    List<DataLakeMeasure> allMeasurements,
-    List<String> measurementsToCount
+      List<DataLakeMeasure> allMeasurements,
+      List<String> measurementsToCount
   );
 
   IDataExplorerQueryManagement getQueryManagement(IDataExplorerSchemaManagement dataExplorerSchemaManagement);
 
   IDataExplorerSchemaManagement getSchemaManagement();
 
-  ITimeSeriesStorage getTimeseriesStorage(DataLakeMeasure measure);
+  default ITimeSeriesStorage getTimeseriesStorage(DataLakeMeasure measure) {
+    return getTimeseriesStorage(measure, false);
+  }
+
+  ITimeSeriesStorage getTimeseriesStorage(DataLakeMeasure measure, boolean ignoreDuplicates);
 
   IDataLakeMeasurementSanitizer getMeasurementSanitizer(IStreamPipesClient client, DataLakeMeasure measure);
 }
diff --git a/streampipes-data-explorer-influx/src/main/java/org/apache/streampipes/dataexplorer/influx/DataExplorerManagerInflux.java b/streampipes-data-explorer-influx/src/main/java/org/apache/streampipes/dataexplorer/influx/DataExplorerManagerInflux.java
index 1c25d5fbc5..869f314b1d 100644
--- a/streampipes-data-explorer-influx/src/main/java/org/apache/streampipes/dataexplorer/influx/DataExplorerManagerInflux.java
+++ b/streampipes-data-explorer-influx/src/main/java/org/apache/streampipes/dataexplorer/influx/DataExplorerManagerInflux.java
@@ -21,9 +21,9 @@ package org.apache.streampipes.dataexplorer.influx;
 import org.apache.streampipes.client.api.IStreamPipesClient;
 import org.apache.streampipes.commons.environment.Environments;
 import org.apache.streampipes.dataexplorer.DataExplorerSchemaManagement;
+import org.apache.streampipes.dataexplorer.api.IDataExplorerManager;
 import org.apache.streampipes.dataexplorer.api.IDataExplorerQueryManagement;
 import org.apache.streampipes.dataexplorer.api.IDataExplorerSchemaManagement;
-import org.apache.streampipes.dataexplorer.api.IDataExplorerManager;
 import org.apache.streampipes.dataexplorer.api.IDataLakeMeasurementCounter;
 import org.apache.streampipes.dataexplorer.api.IDataLakeMeasurementSanitizer;
 import org.apache.streampipes.dataexplorer.api.ITimeSeriesStorage;
@@ -38,28 +38,33 @@ public class DataExplorerManagerInflux implements IDataExplorerManager {
 
   @Override
   public IDataLakeMeasurementCounter getMeasurementCounter(
-    List<DataLakeMeasure> allMeasurements,
-    List<String> measurementsToCount) {
+      List<DataLakeMeasure> allMeasurements,
+      List<String> measurementsToCount) {
     return new DataLakeMeasurementCounterInflux(allMeasurements, measurementsToCount);
   }
 
   @Override
   public IDataExplorerQueryManagement getQueryManagement(
-    IDataExplorerSchemaManagement dataExplorerSchemaManagement
-    ) {
+      IDataExplorerSchemaManagement dataExplorerSchemaManagement
+  ) {
     return new DataExplorerQueryManagementInflux(dataExplorerSchemaManagement);
   }
 
   @Override
   public IDataExplorerSchemaManagement getSchemaManagement() {
     return new DataExplorerSchemaManagement(StorageDispatcher.INSTANCE
-                                                             .getNoSqlStore()
-                                                             .getDataLakeStorage());
+        .getNoSqlStore()
+        .getDataLakeStorage());
   }
 
   @Override
-  public ITimeSeriesStorage getTimeseriesStorage(DataLakeMeasure measure) {
-    return new TimeSeriesStorageInflux(measure, Environments.getEnvironment(), new InfluxClientProvider());
+  public ITimeSeriesStorage getTimeseriesStorage(DataLakeMeasure measure, boolean ignoreDuplicates) {
+    return new TimeSeriesStorageInflux(
+        measure,
+        ignoreDuplicates,
+        Environments.getEnvironment(),
+        new InfluxClientProvider()
+    );
   }
 
   @Override
diff --git a/streampipes-data-explorer-influx/src/main/java/org/apache/streampipes/dataexplorer/influx/PropertyDuplicateFilter.java b/streampipes-data-explorer-influx/src/main/java/org/apache/streampipes/dataexplorer/influx/PropertyDuplicateFilter.java
new file mode 100644
index 0000000000..fe70b15eae
--- /dev/null
+++ b/streampipes-data-explorer-influx/src/main/java/org/apache/streampipes/dataexplorer/influx/PropertyDuplicateFilter.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.dataexplorer.influx;
+
+import org.apache.streampipes.model.runtime.field.PrimitiveField;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+
+public class PropertyDuplicateFilter {
+
+  private final boolean ignoreDuplicates;
+  private final Map<String, Object> lastValues;
+
+  public PropertyDuplicateFilter(boolean ignoreDuplicates) {
+    this.ignoreDuplicates = ignoreDuplicates;
+    this.lastValues = new HashMap<>();
+  }
+
+  public boolean shouldIgnoreField(String sanitizedRuntimeName,
+                                   PrimitiveField eventPropertyPrimitiveField) {
+    var rawValue = eventPropertyPrimitiveField.getRawValue();
+    boolean shouldIgnore = ignoreDuplicates && lastValues.containsKey(sanitizedRuntimeName)
+        && Objects.equals(lastValues.get(sanitizedRuntimeName), rawValue);
+    lastValues.put(sanitizedRuntimeName, rawValue);
+    return shouldIgnore;
+  }
+}
diff --git a/streampipes-data-explorer-influx/src/main/java/org/apache/streampipes/dataexplorer/influx/PropertyHandler.java b/streampipes-data-explorer-influx/src/main/java/org/apache/streampipes/dataexplorer/influx/PropertyHandler.java
index 74d03ba3e2..a19c7d9ed8 100644
--- a/streampipes-data-explorer-influx/src/main/java/org/apache/streampipes/dataexplorer/influx/PropertyHandler.java
+++ b/streampipes-data-explorer-influx/src/main/java/org/apache/streampipes/dataexplorer/influx/PropertyHandler.java
@@ -34,10 +34,13 @@ public class PropertyHandler {
 
   private static final Logger LOG = LoggerFactory.getLogger(PropertyHandler.class);
 
-  private RawFieldSerializer rawFieldSerializer;
+  private final RawFieldSerializer rawFieldSerializer;
+  private final PropertyDuplicateFilter duplicateFilter;
 
-  public PropertyHandler() {
+
+  public PropertyHandler(PropertyDuplicateFilter duplicateFilter) {
     rawFieldSerializer = new RawFieldSerializer();
+    this.duplicateFilter = duplicateFilter;
   }
 
   /**
@@ -109,30 +112,32 @@ public class PropertyHandler {
       String sanitizedRuntimeName,
       PrimitiveField eventPropertyPrimitiveField
   ) {
-    // Store property according to property type
-    if (XSD.INTEGER.toString()
-                   .equals(runtimeType)) {
-      handleIntegerProperty(p, sanitizedRuntimeName, eventPropertyPrimitiveField);
-    } else if (XSD.LONG.toString()
-                       .equals(runtimeType)) {
-      handleLongProperty(p, sanitizedRuntimeName, eventPropertyPrimitiveField);
-    } else if (XSD.FLOAT.toString()
-                        .equals(runtimeType)) {
-      handleFloatProperty(p, sanitizedRuntimeName, eventPropertyPrimitiveField);
-    } else if (XSD.DOUBLE.toString()
-                         .equals(runtimeType)) {
-      handleDoubleProperty(p, sanitizedRuntimeName, eventPropertyPrimitiveField);
-    } else if (XSD.BOOLEAN.toString()
-                          .equals(runtimeType)) {
-      handleBooleanProperty(p, sanitizedRuntimeName, eventPropertyPrimitiveField);
-    } else if (SO.NUMBER.equals(runtimeType)) {
-      handleDoubleProperty(p, sanitizedRuntimeName, eventPropertyPrimitiveField);
-    } else {
-      handleStringProperty(p, sanitizedRuntimeName, eventPropertyPrimitiveField);
+
+    if (!duplicateFilter.shouldIgnoreField(sanitizedRuntimeName, eventPropertyPrimitiveField)) {
+      // Store property according to property type
+      if (XSD.INTEGER.toString()
+          .equals(runtimeType)) {
+        handleIntegerProperty(p, sanitizedRuntimeName, eventPropertyPrimitiveField);
+      } else if (XSD.LONG.toString()
+          .equals(runtimeType)) {
+        handleLongProperty(p, sanitizedRuntimeName, eventPropertyPrimitiveField);
+      } else if (XSD.FLOAT.toString()
+          .equals(runtimeType)) {
+        handleFloatProperty(p, sanitizedRuntimeName, eventPropertyPrimitiveField);
+      } else if (XSD.DOUBLE.toString()
+          .equals(runtimeType)) {
+        handleDoubleProperty(p, sanitizedRuntimeName, eventPropertyPrimitiveField);
+      } else if (XSD.BOOLEAN.toString()
+          .equals(runtimeType)) {
+        handleBooleanProperty(p, sanitizedRuntimeName, eventPropertyPrimitiveField);
+      } else if (SO.NUMBER.equals(runtimeType)) {
+        handleDoubleProperty(p, sanitizedRuntimeName, eventPropertyPrimitiveField);
+      } else {
+        handleStringProperty(p, sanitizedRuntimeName, eventPropertyPrimitiveField);
+      }
     }
   }
 
-
   private void handleStringProperty(
       Point.Builder p,
       String sanitizedRuntimeName,
diff --git a/streampipes-data-explorer-influx/src/main/java/org/apache/streampipes/dataexplorer/influx/TimeSeriesStorageInflux.java b/streampipes-data-explorer-influx/src/main/java/org/apache/streampipes/dataexplorer/influx/TimeSeriesStorageInflux.java
index fa35cbe9b9..799808541e 100644
--- a/streampipes-data-explorer-influx/src/main/java/org/apache/streampipes/dataexplorer/influx/TimeSeriesStorageInflux.java
+++ b/streampipes-data-explorer-influx/src/main/java/org/apache/streampipes/dataexplorer/influx/TimeSeriesStorageInflux.java
@@ -38,15 +38,23 @@ public class TimeSeriesStorageInflux extends TimeSeriesStorage {
 
   private final PropertyHandler propertyHandler;
 
+  public TimeSeriesStorageInflux(
+      DataLakeMeasure measure,
+      Environment environment,
+      InfluxClientProvider influxClientProvider
+  ) throws SpRuntimeException {
+    this(measure, false, environment, influxClientProvider);
+  }
 
   public TimeSeriesStorageInflux(
       DataLakeMeasure measure,
+      boolean ignoreDuplicates,
       Environment environment,
       InfluxClientProvider influxClientProvider
   ) throws SpRuntimeException {
     super(measure);
     this.influxDb = influxClientProvider.getSetUpInfluxDBClient(environment);
-    propertyHandler = new PropertyHandler();
+    propertyHandler = new PropertyHandler(new PropertyDuplicateFilter(ignoreDuplicates));
   }
 
   protected void writeToTimeSeriesStorage(Event event) throws SpRuntimeException {
diff --git a/streampipes-data-explorer-iotdb/src/main/java/org/apache/streampipes/dataexplorer/iotdb/DataExplorerManagerIotDb.java b/streampipes-data-explorer-iotdb/src/main/java/org/apache/streampipes/dataexplorer/iotdb/DataExplorerManagerIotDb.java
index 97ef58e99e..612c2dee6c 100644
--- a/streampipes-data-explorer-iotdb/src/main/java/org/apache/streampipes/dataexplorer/iotdb/DataExplorerManagerIotDb.java
+++ b/streampipes-data-explorer-iotdb/src/main/java/org/apache/streampipes/dataexplorer/iotdb/DataExplorerManagerIotDb.java
@@ -56,7 +56,7 @@ public class DataExplorerManagerIotDb implements IDataExplorerManager {
   }
 
   @Override
-  public ITimeSeriesStorage getTimeseriesStorage(DataLakeMeasure measure) {
+  public ITimeSeriesStorage getTimeseriesStorage(DataLakeMeasure measure, boolean ignoreDuplicates) {
     return new TimeSeriesStorageIotDb(measure, new IotDbPropertyConverter(), new IotDbSessionProvider());
   }
 
diff --git a/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/ImageStoreUtils.java b/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/ImageStoreUtils.java
index 59d4719a7d..c7e226c3ed 100644
--- a/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/ImageStoreUtils.java
+++ b/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/ImageStoreUtils.java
@@ -29,10 +29,7 @@ public class ImageStoreUtils {
 
   public static List<EventProperty> getImageProperties(DataLakeMeasure measure) {
     return measure.getEventSchema().getEventProperties().stream()
-        .filter(eventProperty -> eventProperty.getDomainProperties() != null
-            && !eventProperty.getDomainProperties()
-                             .isEmpty()
-            && eventProperty.getDomainProperties().get(0).toString().equals(SPSensor.IMAGE))
+        .filter(eventProperty -> SPSensor.IMAGE.equalsIgnoreCase(eventProperty.getSemanticType()))
         .collect(Collectors.toList());
   }
 }
diff --git a/streampipes-extensions-api/src/main/java/org/apache/streampipes/extensions/api/extractor/IParameterExtractor.java b/streampipes-extensions-api/src/main/java/org/apache/streampipes/extensions/api/extractor/IParameterExtractor.java
index 396f0f3961..2fd8e40f76 100644
--- a/streampipes-extensions-api/src/main/java/org/apache/streampipes/extensions/api/extractor/IParameterExtractor.java
+++ b/streampipes-extensions-api/src/main/java/org/apache/streampipes/extensions/api/extractor/IParameterExtractor.java
@@ -60,6 +60,8 @@ public interface IParameterExtractor {
 
   <V> List<V> selectedMultiValues(String internalName, Class<V> targetClass);
 
+  <V> List<V> selectedMultiValuesInternalNames(String internalName, Class<V> targetClass);
+
   <V> List<V> selectedTreeNodesInternalNames(String internalName,
                                              Class<V> targetClass);
 
@@ -102,4 +104,6 @@ public interface IParameterExtractor {
   List<String> getEventPropertiesSelectorByScope(PropertyScope scope);
 
   List<EventProperty> getEventPropertiesByScope(PropertyScope scope);
+
+  List<EventProperty> getInputEventProperties(int streamIndex);
 }
diff --git a/streampipes-extensions-management/src/main/java/org/apache/streampipes/extensions/management/connect/adapter/parser/json/GeoJsonParser.java b/streampipes-extensions-management/src/main/java/org/apache/streampipes/extensions/management/connect/adapter/parser/json/GeoJsonParser.java
index 0405a87ca2..f028ccfd12 100644
--- a/streampipes-extensions-management/src/main/java/org/apache/streampipes/extensions/management/connect/adapter/parser/json/GeoJsonParser.java
+++ b/streampipes-extensions-management/src/main/java/org/apache/streampipes/extensions/management/connect/adapter/parser/json/GeoJsonParser.java
@@ -23,7 +23,6 @@ import org.apache.streampipes.extensions.api.connect.IParserEventHandler;
 import org.apache.streampipes.extensions.management.connect.adapter.parser.util.JsonEventProperty;
 import org.apache.streampipes.model.connect.guess.GuessSchema;
 import org.apache.streampipes.model.schema.EventProperty;
-import org.apache.streampipes.model.schema.EventPropertyPrimitive;
 import org.apache.streampipes.sdk.builder.adapter.GuessSchemaBuilder;
 import org.apache.streampipes.vocabulary.Geo;
 import org.apache.streampipes.vocabulary.SO;
@@ -41,9 +40,6 @@ import org.slf4j.LoggerFactory;
 
 import java.io.IOException;
 import java.io.InputStream;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.Arrays;
 import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
@@ -147,12 +143,8 @@ public class GeoJsonParser extends JsonParser {
 
   private EventProperty getEventPropertyGeoJson(String name, Object value, String domain) {
     EventProperty eventProperty = JsonEventProperty.getEventProperty(name, value);
-    try {
-      ((EventPropertyPrimitive) eventProperty).setDomainProperties(Arrays.asList(new URI(domain)));
+    eventProperty.setSemanticType(domain);
 
-    } catch (URISyntaxException e) {
-      LOG.error(e.getMessage());
-    }
     return eventProperty;
   }
 
diff --git a/streampipes-extensions-management/src/main/java/org/apache/streampipes/extensions/management/util/EventSchemaUtils.java b/streampipes-extensions-management/src/main/java/org/apache/streampipes/extensions/management/util/EventSchemaUtils.java
index f0a7020447..0f9a46b210 100644
--- a/streampipes-extensions-management/src/main/java/org/apache/streampipes/extensions/management/util/EventSchemaUtils.java
+++ b/streampipes-extensions-management/src/main/java/org/apache/streampipes/extensions/management/util/EventSchemaUtils.java
@@ -24,7 +24,6 @@ import org.apache.streampipes.model.schema.EventPropertyPrimitive;
 import org.apache.streampipes.model.schema.EventSchema;
 import org.apache.streampipes.vocabulary.SO;
 
-import java.net.URI;
 import java.util.List;
 import java.util.Optional;
 
@@ -47,7 +46,7 @@ public class EventSchemaUtils {
 
   private static Optional<EventPropertyPrimitive> getTimstampProperty(List<EventProperty> eventProperties) {
     for (EventProperty ep : eventProperties) {
-      if (ep instanceof EventPropertyPrimitive && ep.getDomainProperties().contains(URI.create(SO.DATE_TIME))) {
+      if (ep instanceof EventPropertyPrimitive && SO.DATE_TIME.equalsIgnoreCase(ep.getSemanticType())) {
         return Optional.of((EventPropertyPrimitive) ep);
       }
 
diff --git a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/protocol/stream/FileReplayAdapter.java b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/protocol/stream/FileReplayAdapter.java
index ed0d256605..a5a42a4c09 100644
--- a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/protocol/stream/FileReplayAdapter.java
+++ b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/protocol/stream/FileReplayAdapter.java
@@ -53,7 +53,6 @@ import org.slf4j.LoggerFactory;
 
 import java.io.IOException;
 import java.io.InputStream;
-import java.net.URI;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.Executors;
@@ -212,9 +211,7 @@ public class FileReplayAdapter implements StreamPipesAdapter {
         .getEventSchema()
         .getEventProperties()
         .stream()
-        .filter(eventProperty ->
-                    eventProperty.getDomainProperties()
-                                 .contains(URI.create(SO.DATE_TIME)))
+        .filter(eventProperty -> SO.DATE_TIME.equals(eventProperty.getSemanticType()))
         .findFirst();
 
     if (timestampField.isEmpty()) {
diff --git a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/protocol/stream/HttpServerProtocol.java b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/protocol/stream/HttpServerProtocol.java
index 88a08a6d94..ed49af0e31 100644
--- a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/protocol/stream/HttpServerProtocol.java
+++ b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/protocol/stream/HttpServerProtocol.java
@@ -51,9 +51,7 @@ import org.apache.streampipes.sdk.utils.Datatypes;
 
 import java.io.IOException;
 import java.io.InputStream;
-import java.net.URI;
 import java.util.ArrayList;
-import java.util.Collections;
 
 public class HttpServerProtocol implements StreamPipesAdapter {
 
@@ -86,8 +84,7 @@ public class HttpServerProtocol implements StreamPipesAdapter {
     primitive.setRuntimeName(memberExtractor.singleValueParameter(EP_RUNTIME_NAME, String.class));
     primitive.setRuntimeType(extractRuntimeType(memberExtractor.selectedSingleValue(EP_RUNTIME_TYPE, String.class)));
     primitive
-        .setDomainProperties(Collections
-            .singletonList(URI.create(memberExtractor.singleValueParameter(EP_DOMAIN_PROPERTY, String.class))));
+        .setSemanticType(memberExtractor.singleValueParameter(EP_DOMAIN_PROPERTY, String.class));
     return primitive;
   }
 
diff --git a/streampipes-extensions/streampipes-processors-filters-siddhi/src/main/java/org/apache/streampipes/processors/siddhi/listcollector/ListCollector.java b/streampipes-extensions/streampipes-processors-filters-siddhi/src/main/java/org/apache/streampipes/processors/siddhi/listcollector/ListCollector.java
index 6d908bd7dc..11cb6bfb98 100644
--- a/streampipes-extensions/streampipes-processors-filters-siddhi/src/main/java/org/apache/streampipes/processors/siddhi/listcollector/ListCollector.java
+++ b/streampipes-extensions/streampipes-processors-filters-siddhi/src/main/java/org/apache/streampipes/processors/siddhi/listcollector/ListCollector.java
@@ -83,16 +83,16 @@ public class ListCollector extends StreamPipesSiddhiProcessor
     List<EventProperty> selectedProperty = extractor
         .getInputStreamEventPropertySubset(Collections.singletonList(propertySelector));
 
-    if (selectedProperty.size() > 0) {
+    if (!selectedProperty.isEmpty()) {
       EventPropertyPrimitive prop = (EventPropertyPrimitive) selectedProperty.get(0);
       String newPropertyName = prop.getRuntimeName() + "_list";
       String newDatatype = prop.getRuntimeType();
-      String newDomainProperty = prop.getDomainProperties().get(0).toString();
+      String newSemanticType = prop.getSemanticType();
 
       EventPropertyList ep = EpProperties.listEp(Labels.from("list", "", ""),
           newPropertyName,
           Datatypes.fromDatatypeString(newDatatype),
-          newDomainProperty);
+          newSemanticType);
 
       inputSchema.addEventProperty(ep);
     }
diff --git a/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/InternalSinksExtensionModuleExports.java b/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/InternalSinksExtensionModuleExports.java
index 8dba55f9aa..72bcbcb7d1 100644
--- a/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/InternalSinksExtensionModuleExports.java
+++ b/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/InternalSinksExtensionModuleExports.java
@@ -24,6 +24,7 @@ import org.apache.streampipes.extensions.api.migration.IModelMigrator;
 import org.apache.streampipes.extensions.api.pe.IStreamPipesPipelineElement;
 import org.apache.streampipes.sinks.internal.jvm.datalake.DataLakeSink;
 import org.apache.streampipes.sinks.internal.jvm.datalake.migrations.DataLakeSinkMigrationV1;
+import org.apache.streampipes.sinks.internal.jvm.datalake.migrations.DataLakeSinkMigrationV2;
 import org.apache.streampipes.sinks.internal.jvm.notification.InternalStreamPipesNotificationSink;
 
 import java.util.Collections;
@@ -45,6 +46,8 @@ public class InternalSinksExtensionModuleExports implements IExtensionModuleExpo
 
   @Override
   public List<IModelMigrator<?, ?>> migrators() {
-    return List.of(new DataLakeSinkMigrationV1());
+    return List.of(
+        new DataLakeSinkMigrationV1(),
+        new DataLakeSinkMigrationV2());
   }
 }
diff --git a/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/datalake/DataLakeDimensionProvider.java b/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/datalake/DataLakeDimensionProvider.java
new file mode 100644
index 0000000000..17ed2b9c87
--- /dev/null
+++ b/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/datalake/DataLakeDimensionProvider.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.sinks.internal.jvm.datalake;
+
+import org.apache.streampipes.model.schema.EventProperty;
+import org.apache.streampipes.model.schema.EventPropertyPrimitive;
+import org.apache.streampipes.model.schema.PropertyScope;
+import org.apache.streampipes.model.staticproperty.Option;
+import org.apache.streampipes.model.staticproperty.RuntimeResolvableAnyStaticProperty;
+import org.apache.streampipes.sdk.utils.Datatypes;
+import org.apache.streampipes.vocabulary.SO;
+
+import java.util.List;
+
+public class DataLakeDimensionProvider {
+
+  public void applyOptions(List<EventProperty> inputFields,
+                           RuntimeResolvableAnyStaticProperty staticProperty) {
+    var primitiveFields = getPrimitiveFields(inputFields);
+    primitiveFields
+        .forEach(field -> addFieldIfNotExists(field, staticProperty.getOptions()));
+    staticProperty.getOptions().removeIf(o -> !existsInFields(o, primitiveFields));
+  }
+
+  private List<EventPropertyPrimitive> getPrimitiveFields(List<EventProperty> inputFields) {
+    return inputFields
+        .stream()
+        .filter(field -> field instanceof EventPropertyPrimitive)
+        .filter(field -> satisfiesFilter((EventPropertyPrimitive) field))
+        .map(field -> (EventPropertyPrimitive) field)
+        .toList();
+  }
+
+  private boolean satisfiesFilter(EventPropertyPrimitive field) {
+    return !field.getRuntimeType().equals(Datatypes.Float.toString())
+        &&  !(SO.DATE_TIME.equalsIgnoreCase(field.getSemanticType()));
+  }
+
+  private void addFieldIfNotExists(EventPropertyPrimitive field,
+                                   List<Option> options) {
+    if (options.stream().noneMatch(o -> o.getName().equals(field.getRuntimeName()))) {
+      options.add(new Option(
+          field.getRuntimeName(),
+          PropertyScope.valueOf(field.getPropertyScope()) == PropertyScope.DIMENSION_PROPERTY)
+      );
+    }
+  }
+
+  private boolean existsInFields(Option o,
+                                 List<EventPropertyPrimitive> primitiveFields) {
+    return primitiveFields.stream().anyMatch(field -> field.getRuntimeName().equals(o.getName()));
+  }
+}
diff --git a/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/datalake/DataLakeSink.java b/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/datalake/DataLakeSink.java
index ef88bbdcdc..5cdeae32a0 100644
--- a/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/datalake/DataLakeSink.java
+++ b/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/datalake/DataLakeSink.java
@@ -22,14 +22,19 @@ import org.apache.streampipes.commons.environment.Environments;
 import org.apache.streampipes.commons.exceptions.SpRuntimeException;
 import org.apache.streampipes.dataexplorer.TimeSeriesStore;
 import org.apache.streampipes.dataexplorer.management.DataExplorerDispatcher;
+import org.apache.streampipes.extensions.api.extractor.IStaticPropertyExtractor;
 import org.apache.streampipes.extensions.api.pe.context.EventSinkRuntimeContext;
+import org.apache.streampipes.extensions.api.runtime.SupportsRuntimeConfig;
 import org.apache.streampipes.model.DataSinkType;
 import org.apache.streampipes.model.datalake.DataLakeMeasure;
 import org.apache.streampipes.model.datalake.DataLakeMeasureSchemaUpdateStrategy;
 import org.apache.streampipes.model.extensions.ExtensionAssetType;
 import org.apache.streampipes.model.graph.DataSinkDescription;
 import org.apache.streampipes.model.runtime.Event;
+import org.apache.streampipes.model.schema.EventSchema;
 import org.apache.streampipes.model.schema.PropertyScope;
+import org.apache.streampipes.model.staticproperty.RuntimeResolvableAnyStaticProperty;
+import org.apache.streampipes.model.staticproperty.StaticProperty;
 import org.apache.streampipes.sdk.builder.DataSinkBuilder;
 import org.apache.streampipes.sdk.builder.StreamRequirementsBuilder;
 import org.apache.streampipes.sdk.helpers.EpRequirements;
@@ -39,15 +44,21 @@ import org.apache.streampipes.sdk.helpers.Options;
 import org.apache.streampipes.wrapper.params.compat.SinkParams;
 import org.apache.streampipes.wrapper.standalone.StreamPipesDataSink;
 
-public class DataLakeSink extends StreamPipesDataSink {
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class DataLakeSink extends StreamPipesDataSink implements SupportsRuntimeConfig {
 
   private static final String DATABASE_MEASUREMENT_KEY = "db_measurement";
   private static final String TIMESTAMP_MAPPING_KEY = "timestamp_mapping";
   public static final String SCHEMA_UPDATE_KEY = "schema_update";
+  public static final String DIMENSIONS_KEY = "dimensions_selection";
+  public static final String IGNORE_DUPLICATES_KEY = "ignore_duplicates";
 
   public static final String SCHEMA_UPDATE_OPTION = "Update schema";
 
   public static final String EXTEND_EXISTING_SCHEMA_OPTION = "Extend existing schema";
+  private static final Logger LOG = LoggerFactory.getLogger(DataLakeSink.class);
 
   private TimeSeriesStore timeSeriesStore;
 
@@ -55,25 +66,26 @@ public class DataLakeSink extends StreamPipesDataSink {
   @Override
   public DataSinkDescription declareModel() {
     return DataSinkBuilder
-      .create("org.apache.streampipes.sinks.internal.jvm.datalake", 1)
-      .withLocales(Locales.EN)
-      .withAssets(ExtensionAssetType.DOCUMENTATION, ExtensionAssetType.ICON)
-      .category(DataSinkType.INTERNAL)
-      .requiredStream(StreamRequirementsBuilder
-                        .create()
-                        .requiredPropertyWithUnaryMapping(
-                          EpRequirements.timestampReq(),
-                          Labels.withId(TIMESTAMP_MAPPING_KEY),
-                          PropertyScope.NONE
-                        )
-                        .build())
-      .requiredTextParameter(Labels.withId(DATABASE_MEASUREMENT_KEY))
-      .requiredSingleValueSelection(
-        Labels.withId(SCHEMA_UPDATE_KEY),
-        Options.from(SCHEMA_UPDATE_OPTION, EXTEND_EXISTING_SCHEMA_OPTION)
-      )
-
-      .build();
+        .create("org.apache.streampipes.sinks.internal.jvm.datalake", 2)
+        .withLocales(Locales.EN)
+        .withAssets(ExtensionAssetType.DOCUMENTATION, ExtensionAssetType.ICON)
+        .category(DataSinkType.INTERNAL)
+        .requiredStream(StreamRequirementsBuilder
+            .create()
+            .requiredPropertyWithUnaryMapping(
+                EpRequirements.timestampReq(),
+                Labels.withId(TIMESTAMP_MAPPING_KEY),
+                PropertyScope.NONE
+            )
+            .build())
+        .requiredTextParameter(Labels.withId(DATABASE_MEASUREMENT_KEY))
+        .requiredSingleValueSelection(
+            Labels.withId(SCHEMA_UPDATE_KEY),
+            Options.from(SCHEMA_UPDATE_OPTION, EXTEND_EXISTING_SCHEMA_OPTION)
+        )
+        .requiredMultiValueSelectionFromContainer(Labels.withId(DIMENSIONS_KEY))
+        .requiredSlideToggle(Labels.withId(IGNORE_DUPLICATES_KEY), false)
+        .build();
   }
 
   @Override
@@ -81,9 +93,21 @@ public class DataLakeSink extends StreamPipesDataSink {
     var extractor = parameters.extractor();
     var timestampField = extractor.mappingPropertyValue(TIMESTAMP_MAPPING_KEY);
     var measureName = extractor.singleValueParameter(DATABASE_MEASUREMENT_KEY, String.class);
-    var eventSchema = parameters.getInputSchemaInfos()
-                                .get(0)
-                                .getEventSchema();
+    var dimensions = extractor.selectedMultiValues(DIMENSIONS_KEY, String.class);
+    var ignoreDuplicates = extractor.slideToggleValue(IGNORE_DUPLICATES_KEY);
+    var eventSchema = new EventSchema(parameters.getInputSchemaInfos()
+        .get(0)
+        .getEventSchema()
+        .getEventProperties()
+        .stream()
+        .peek(ep -> {
+          if (dimensions.contains(ep.getRuntimeName())) {
+            LOG.info("Using {} as dimension", ep.getRuntimeName());
+            ep.setPropertyScope(PropertyScope.DIMENSION_PROPERTY.name());
+          }
+        })
+        .toList()
+    );
 
 
     var measure = new DataLakeMeasure(measureName, timestampField, eventSchema);
@@ -101,7 +125,7 @@ public class DataLakeSink extends StreamPipesDataSink {
         .sanitizeAndRegister();
 
     this.timeSeriesStore = new TimeSeriesStore(
-        new DataExplorerDispatcher().getDataExplorerManager().getTimeseriesStorage(measure),
+        new DataExplorerDispatcher().getDataExplorerManager().getTimeseriesStorage(measure, ignoreDuplicates),
         measure,
         Environments.getEnvironment(),
         true
@@ -118,4 +142,13 @@ public class DataLakeSink extends StreamPipesDataSink {
   public void onDetach() throws SpRuntimeException {
     this.timeSeriesStore.close();
   }
+
+  @Override
+  public StaticProperty resolveConfiguration(String staticPropertyInternalName,
+                                             IStaticPropertyExtractor extractor) {
+    var staticProperty = extractor.getStaticPropertyByName(DIMENSIONS_KEY, RuntimeResolvableAnyStaticProperty.class);
+    var inputFields = extractor.getInputEventProperties(0);
+    new DataLakeDimensionProvider().applyOptions(inputFields, staticProperty);
+    return staticProperty;
+  }
 }
diff --git a/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/datalake/migrations/DataLakeSinkMigrationV2.java b/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/datalake/migrations/DataLakeSinkMigrationV2.java
new file mode 100644
index 0000000000..5a81ba4cd7
--- /dev/null
+++ b/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/datalake/migrations/DataLakeSinkMigrationV2.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.sinks.internal.jvm.datalake.migrations;
+
+import org.apache.streampipes.extensions.api.extractor.IDataSinkParameterExtractor;
+import org.apache.streampipes.extensions.api.migration.IDataSinkMigrator;
+import org.apache.streampipes.model.extensions.svcdiscovery.SpServiceTagPrefix;
+import org.apache.streampipes.model.graph.DataSinkInvocation;
+import org.apache.streampipes.model.migration.MigrationResult;
+import org.apache.streampipes.model.migration.ModelMigratorConfig;
+import org.apache.streampipes.model.staticproperty.RuntimeResolvableAnyStaticProperty;
+import org.apache.streampipes.model.staticproperty.SlideToggleStaticProperty;
+import org.apache.streampipes.sdk.helpers.Labels;
+import org.apache.streampipes.sinks.internal.jvm.datalake.DataLakeDimensionProvider;
+import org.apache.streampipes.sinks.internal.jvm.datalake.DataLakeSink;
+
+public class DataLakeSinkMigrationV2 implements IDataSinkMigrator {
+  @Override
+  public ModelMigratorConfig config() {
+    return new ModelMigratorConfig(
+        "org.apache.streampipes.sinks.internal.jvm.datalake",
+        SpServiceTagPrefix.DATA_SINK,
+        1,
+        2
+    );
+  }
+
+  @Override
+  public MigrationResult<DataSinkInvocation> migrate(DataSinkInvocation element,
+                                                     IDataSinkParameterExtractor extractor) throws RuntimeException {
+    addDimensionSelection(element);
+    addDuplicateToggle(element);
+    return MigrationResult.success(element);
+  }
+
+  private void addDimensionSelection(DataSinkInvocation element) {
+    var label = Labels.from(
+        DataLakeSink.DIMENSIONS_KEY,
+        "Dimensions",
+        "Selected fields will be stored as dimensions."
+    );
+    var staticProperty = new RuntimeResolvableAnyStaticProperty(
+        label.getInternalId(),
+        label.getLabel(),
+        label.getDescription()
+    );
+    var inputFields = element.getInputStreams().get(0).getEventSchema().getEventProperties();
+    new DataLakeDimensionProvider().applyOptions(inputFields, staticProperty);
+
+    element.getStaticProperties().add(staticProperty);
+  }
+
+  private void addDuplicateToggle(DataSinkInvocation element) {
+    var label = Labels.from(
+        DataLakeSink.IGNORE_DUPLICATES_KEY,
+        "Ignore duplicates",
+        "Fields having the same value than the previous event are not stored."
+    );
+    var staticProperty = new SlideToggleStaticProperty(
+        label.getInternalId(),
+        label.getLabel(),
+        label.getDescription(),
+        false);
+
+    element.getStaticProperties().add(staticProperty);
+  }
+}
diff --git a/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/resources/org.apache.streampipes.sinks.internal.jvm.datalake/documentation.md b/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/resources/org.apache.streampipes.sinks.internal.jvm.datalake/documentation.md
index 2d58b7e3d9..b9dde8e06d 100644
--- a/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/resources/org.apache.streampipes.sinks.internal.jvm.datalake/documentation.md
+++ b/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/resources/org.apache.streampipes.sinks.internal.jvm.datalake/documentation.md
@@ -41,6 +41,16 @@ This sink requires an event that provides a timestamp value (a field that is mar
 
 ## Configuration
 
+### Dimensions
+
+The fields which will be stored as dimensional values in the time series storage. Dimensions are typically identifiers 
+such as the ID of a sensor.
+Dimensions support grouping in the data explorer, but will be converted to a text-based field and provide less advanced 
+filtering capabilities.
+
+Be careful when modifying dimensions of existing pipelines! This might have impact on how you are able to view data in 
+the data explorer due to schema incompatibilities.
+
 ### Identifier
 
 The name of the measurement (table) where the events are stored.
@@ -60,3 +70,22 @@ The Schema Update Options dictate the behavior when encountering a measurement (
 - **Description:** Keeps old event fields in the event schema.
 - **Strategy:** This follows an append-only strategy, allowing continued work with historic data.
 - **Consideration:** Old properties may exist for which no new data is generated.
+
+
+### Dimensions
+
+Select fields which will be marked as dimensions. Dimensions reflect tags in the underlying time-series database. 
+Dimensions support grouping operations and can be used for fields with a limited set of values, e.g., boolean flags or 
+fields representing IDs. Dimensions are not a good choice for fields with a high number of different values since they 
+slow down database queries.
+
+By default, all fields which are marked as dimensions in the metadata are chosen and can be manually overridden 
+with this configuration.
+
+Data types which can be marked as dimensional values are booleans, integer, and strings.
+
+### Ignore Duplicates
+
+Before writing an event to the time series storage, a duplicate check is performed. By activating this option, only 
+fields having a different value than the previous event are stored. 
+This setting only affects measurement fields, not dimensions.
diff --git a/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/resources/org.apache.streampipes.sinks.internal.jvm.datalake/strings.en b/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/resources/org.apache.streampipes.sinks.internal.jvm.datalake/strings.en
index 0b604bdfd9..d1fcc39c7e 100644
--- a/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/resources/org.apache.streampipes.sinks.internal.jvm.datalake/strings.en
+++ b/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/resources/org.apache.streampipes.sinks.internal.jvm.datalake/strings.en
@@ -26,3 +26,9 @@ timestamp_mapping.description=The value which contains a timestamp
 
 schema_update.title=Schema Update
 schema_update.description=Update existing schemas with the new one or extend the existing schema with new properties
+
+dimensions_selection.title=Dimensions
+dimensions_selection.description=Selected fields will be stored as dimensions.
+
+ignore_duplicates.title=Ignore duplicates
+ignore_duplicates.description=Fields having the same value than the previous event are not stored. This only affects measurements, not tags.
diff --git a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/matching/MatchingResultType.java b/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/matching/MatchingResultType.java
index 225a899533..225fe1180d 100644
--- a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/matching/MatchingResultType.java
+++ b/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/matching/MatchingResultType.java
@@ -22,8 +22,8 @@ public enum MatchingResultType {
 
   DATATYPE_MATCH("Datatype Match", "A required datatype is not present in the input event property."),
   STREAM_MATCH("Stream Match", ""),
-  DOMAIN_PROPERTY_MATCH("Domain Property Match",
-      "A required domain property is not present in the input event property."),
+  SEMANTIC_TYPE_MATCH("Semantic Type Match",
+      "A required semantic type is not present in the input event property."),
   FORMAT_MATCH("Format Match", "No supported transport format found."),
   GROUNDING_MATCH("Grounding Match", ""),
   PROTOCOL_MATCH("Protocol Match", "No supported communication protocol found."),
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/dashboard/DashboardItem.java b/streampipes-model/src/main/java/org/apache/streampipes/model/dashboard/DashboardItem.java
index c7962b0411..81759642cb 100644
--- a/streampipes-model/src/main/java/org/apache/streampipes/model/dashboard/DashboardItem.java
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/dashboard/DashboardItem.java
@@ -18,6 +18,7 @@
 package org.apache.streampipes.model.dashboard;
 
 import java.util.List;
+import java.util.Map;
 
 public class DashboardItem {
 
@@ -31,6 +32,7 @@ public class DashboardItem {
   private Integer rows;
   private Integer x;
   private Integer y;
+  private Map<String, Object> timeSettings;
 
   public DashboardItem() {
 
@@ -99,4 +101,12 @@ public class DashboardItem {
   public void setY(Integer y) {
     this.y = y;
   }
+
+  public Map<String, Object> getTimeSettings() {
+    return timeSettings;
+  }
+
+  public void setTimeSettings(Map<String, Object> timeSettings) {
+    this.timeSettings = timeSettings;
+  }
 }
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/schema/EventProperty.java b/streampipes-model/src/main/java/org/apache/streampipes/model/schema/EventProperty.java
index 2bfc4ce28d..ceddacc02b 100644
--- a/streampipes-model/src/main/java/org/apache/streampipes/model/schema/EventProperty.java
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/schema/EventProperty.java
@@ -19,15 +19,11 @@
 package org.apache.streampipes.model.schema;
 
 import org.apache.streampipes.model.util.ElementIdGenerator;
-import org.apache.streampipes.model.util.ListUtils;
 
 import com.fasterxml.jackson.annotation.JsonSubTypes;
 import com.fasterxml.jackson.annotation.JsonTypeInfo;
 
-import java.net.URI;
-import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 
@@ -45,15 +41,13 @@ public abstract class EventProperty {
   private String label;
   private String description;
   private String runtimeName;
-  private List<URI> domainProperties;
+  private String semanticType;
   private String propertyScope;
   private String runtimeId;
   private Map<String, Object> additionalMetadata;
 
-
   public EventProperty() {
     this.elementId = ElementIdGenerator.makeElementId(EventProperty.class);
-    this.domainProperties = new ArrayList<>();
     this.additionalMetadata = new HashMap<>();
   }
 
@@ -62,21 +56,16 @@ public abstract class EventProperty {
     this.label = other.getLabel();
     this.description = other.getDescription();
     this.runtimeName = other.getRuntimeName();
-    this.domainProperties = other.getDomainProperties();
     this.propertyScope = other.getPropertyScope();
     this.runtimeId = other.getRuntimeId();
     this.additionalMetadata = other.getAdditionalMetadata();
+    this.semanticType = other.getSemanticType();
   }
 
-  public EventProperty(List<URI> subClassOf) {
-    this();
-    this.domainProperties = subClassOf;
-  }
-
-  public EventProperty(String propertyName, List<URI> subClassOf) {
+  public EventProperty(String propertyName, String semanticType) {
     this();
     this.runtimeName = propertyName;
-    this.domainProperties = subClassOf;
+    this.semanticType = semanticType;
   }
 
   public EventProperty(String propertyName) {
@@ -97,14 +86,6 @@ public abstract class EventProperty {
     this.runtimeName = propertyName;
   }
 
-  public List<URI> getDomainProperties() {
-    return domainProperties;
-  }
-
-  public void setDomainProperties(List<URI> subClassOf) {
-    this.domainProperties = subClassOf;
-  }
-
   public String getLabel() {
     return label;
   }
@@ -153,9 +134,17 @@ public abstract class EventProperty {
     this.additionalMetadata = additionalMetadata;
   }
 
+  public String getSemanticType() {
+    return semanticType;
+  }
+
+  public void setSemanticType(String semanticType) {
+    this.semanticType = semanticType;
+  }
+
   @Override
   public int hashCode() {
-    return Objects.hash(elementId, label, description, runtimeName, domainProperties, propertyScope,
+    return Objects.hash(elementId, label, description, runtimeName, semanticType, propertyScope,
         runtimeId);
   }
 
@@ -174,7 +163,7 @@ public abstract class EventProperty {
            && Objects.equals(runtimeName, that.runtimeName)
            && Objects.equals(propertyScope, that.propertyScope)
            && Objects.equals(runtimeId, that.runtimeId)
-           && ListUtils.isEqualList(this.domainProperties, that.domainProperties);
+           && Objects.equals(semanticType, that.semanticType);
   }
 
   @Override
@@ -184,7 +173,7 @@ public abstract class EventProperty {
            + ", label='" + label + '\''
            + ", description='" + description + '\''
            + ", runtimeName='" + runtimeName + '\''
-           + ", domainProperties=" + domainProperties
+           + ", semanticType=" + semanticType
            + ", propertyScope='" + propertyScope + '\''
            + ", runtimeId='" + runtimeId + '\''
            + '}';
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/schema/EventPropertyList.java b/streampipes-model/src/main/java/org/apache/streampipes/model/schema/EventPropertyList.java
index 799a6ee568..98af25f1d1 100644
--- a/streampipes-model/src/main/java/org/apache/streampipes/model/schema/EventPropertyList.java
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/schema/EventPropertyList.java
@@ -20,8 +20,6 @@ package org.apache.streampipes.model.schema;
 
 import org.apache.streampipes.model.util.Cloner;
 
-import java.net.URI;
-import java.util.List;
 import java.util.Objects;
 
 public class EventPropertyList extends EventProperty {
@@ -51,10 +49,9 @@ public class EventPropertyList extends EventProperty {
     this.eventProperty = listProperty;
   }
 
-  public EventPropertyList(String propertyName, EventProperty eventProperty, List<URI> domainProperties) {
-    super(propertyName);
+  public EventPropertyList(String propertyName, EventProperty eventProperty, String semanticType) {
+    super(propertyName, semanticType);
     this.eventProperty = eventProperty;
-    this.setDomainProperties(domainProperties);
   }
 
   public EventProperty getEventProperty() {
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/schema/EventPropertyPrimitive.java b/streampipes-model/src/main/java/org/apache/streampipes/model/schema/EventPropertyPrimitive.java
index e1fa7d40cb..0822c163a4 100644
--- a/streampipes-model/src/main/java/org/apache/streampipes/model/schema/EventPropertyPrimitive.java
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/schema/EventPropertyPrimitive.java
@@ -21,7 +21,6 @@ package org.apache.streampipes.model.schema;
 import org.apache.streampipes.model.util.Cloner;
 
 import java.net.URI;
-import java.util.List;
 import java.util.Objects;
 
 public class EventPropertyPrimitive extends EventProperty {
@@ -44,13 +43,11 @@ public class EventPropertyPrimitive extends EventProperty {
     }
   }
 
-  public EventPropertyPrimitive(List<URI> subClassOf) {
-    super(subClassOf);
-  }
-
-  public EventPropertyPrimitive(String runtimeType, String runtimeName,
-                                String measurementUnit, List<URI> subClassOf) {
-    super(runtimeName, subClassOf);
+  public EventPropertyPrimitive(String runtimeType,
+                                String runtimeName,
+                                String measurementUnit,
+                                String semanticType) {
+    super(runtimeName, semanticType);
     this.runtimeType = runtimeType;
     //this.measurementUnit = measurementUnit;
   }
@@ -92,8 +89,8 @@ public class EventPropertyPrimitive extends EventProperty {
     }
     EventPropertyPrimitive that = (EventPropertyPrimitive) o;
     return Objects.equals(runtimeType, that.runtimeType)
-           && Objects.equals(measurementUnit, that.measurementUnit)
-           && Objects.equals(valueSpecification, that.valueSpecification);
+        && Objects.equals(measurementUnit, that.measurementUnit)
+        && Objects.equals(valueSpecification, that.valueSpecification);
   }
 
   @Override
@@ -104,9 +101,9 @@ public class EventPropertyPrimitive extends EventProperty {
   @Override
   public String toString() {
     return "EventPropertyPrimitive{"
-           + "runtimeType='" + runtimeType + '\''
-           + ", measurementUnit=" + measurementUnit
-           + ", valueSpecification=" + valueSpecification
-           + '}';
+        + "runtimeType='" + runtimeType + '\''
+        + ", measurementUnit=" + measurementUnit
+        + ", valueSpecification=" + valueSpecification
+        + '}';
   }
 }
diff --git a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/output/PropertyDuplicateRemover.java b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/output/PropertyDuplicateRemover.java
index 4106f664da..90a0fdbcc8 100644
--- a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/output/PropertyDuplicateRemover.java
+++ b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/output/PropertyDuplicateRemover.java
@@ -43,29 +43,25 @@ public class PropertyDuplicateRemover {
       int i = 1;
       EventProperty newProperty = p;
       while (isAlreadyDefined(existingProperties, newProperty)) {
-        if (newProperty instanceof EventPropertyPrimitive) {
-          EventPropertyPrimitive primitive = (EventPropertyPrimitive) newProperty;
+        if (newProperty instanceof EventPropertyPrimitive primitive) {
           newProperty = new EventPropertyPrimitive(primitive.getRuntimeType(), primitive.getRuntimeName() + i, "",
-              primitive.getDomainProperties());
+              primitive.getSemanticType());
         }
-        if (newProperty instanceof EventPropertyNested) {
-          EventPropertyNested nested = (EventPropertyNested) newProperty;
+        if (newProperty instanceof EventPropertyNested nested) {
 
           //TODO: hack
           List<EventProperty> nestedProperties = new ArrayList<>();
 
           for (EventProperty np : nested.getEventProperties()) {
-            if (np instanceof EventPropertyPrimitive) {
-              EventPropertyPrimitive thisPrimitive = (EventPropertyPrimitive) np;
+            if (np instanceof EventPropertyPrimitive thisPrimitive) {
               EventProperty newNested =
                   new EventPropertyPrimitive(thisPrimitive.getRuntimeType(), thisPrimitive.getRuntimeName(), "",
-                      thisPrimitive.getDomainProperties());
+                      thisPrimitive.getSemanticType());
               nestedProperties.add(newNested);
             }
 
           }
           newProperty = new EventPropertyNested(nested.getRuntimeName() + i, nestedProperties);
-          //newProperty = new EventPropertyNested(nested.getPropertyName() +i, nested.getEventProperties());
         }
         i++;
       }
diff --git a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/output/TransformOutputSchemaGenerator.java b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/output/TransformOutputSchemaGenerator.java
index 656d10a4a7..902df7dc7d 100644
--- a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/output/TransformOutputSchemaGenerator.java
+++ b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/output/TransformOutputSchemaGenerator.java
@@ -36,7 +36,6 @@ import org.apache.streampipes.model.util.Cloner;
 import org.apache.streampipes.sdk.helpers.Tuple2;
 
 import java.net.URI;
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -158,7 +157,7 @@ public class TransformOutputSchemaGenerator extends OutputSchemaGenerator<Transf
       }
 
     } else if (transformOperationType == TransformOperationType.DOMAIN_PROPERTY_TRANSFORMATION) {
-      eventProperty.setDomainProperties(Collections.singletonList(URI.create(value)));
+      eventProperty.setSemanticType(value);
 
     } else if (transformOperationType == TransformOperationType.RUNTIME_NAME_TRANSFORMATION) {
       eventProperty.setRuntimeName(value);
diff --git a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/v2/ListPropertyMatch.java b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/v2/ListPropertyMatch.java
index a27f1350cd..6f9f121e2e 100644
--- a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/v2/ListPropertyMatch.java
+++ b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/v2/ListPropertyMatch.java
@@ -30,14 +30,14 @@ public class ListPropertyMatch implements Matcher<EventPropertyList, EventProper
     if (requirement.getEventProperty() == null) {
       return true;
     } else {
-      return domainPropertyMatch(offer, requirement, errorLog) && listItemMatch(offer, requirement,
+      return semanticTypeMatch(offer, requirement, errorLog) && listItemMatch(offer, requirement,
           errorLog);
     }
   }
 
-  private boolean domainPropertyMatch(EventPropertyList offer, EventPropertyList requirement,
+  private boolean semanticTypeMatch(EventPropertyList offer, EventPropertyList requirement,
                                       List<MatchingResultMessage> errorLog) {
-    return new DomainPropertyMatch().match(offer.getDomainProperties(), requirement.getDomainProperties(),
+    return new SemanticTypeMatch().match(offer.getSemanticType(), requirement.getSemanticType(),
         errorLog);
   }
 
diff --git a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/v2/PrimitivePropertyMatch.java b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/v2/PrimitivePropertyMatch.java
index 82fa379c96..45124c0a57 100644
--- a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/v2/PrimitivePropertyMatch.java
+++ b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/v2/PrimitivePropertyMatch.java
@@ -38,16 +38,16 @@ public class PrimitivePropertyMatch extends AbstractMatcher<EventPropertyPrimiti
 
     boolean matchesUnit = unitMatch(offer.getMeasurementUnit(), requirement.getMeasurementUnit(), errorLog);
     boolean matchesDatatype = datatypeMatch(offer.getRuntimeType(), requirement.getRuntimeType(), errorLog);
-    boolean matchesDomainProperty = domainPropertyMatch(offer.getDomainProperties(), requirement.getDomainProperties
-        (), errorLog);
+    boolean matchesSemanticType = semanticTypeMatch(offer.getSemanticType(), requirement.getSemanticType(), errorLog);
 
     return MatchingUtils.nullCheck(offer, requirement)
-        || (matchesUnit && matchesDatatype && matchesDomainProperty);
+        || (matchesUnit && matchesDatatype && matchesSemanticType);
   }
 
-  private boolean domainPropertyMatch(List<URI> offer,
-                                      List<URI> requirement, List<MatchingResultMessage> errorLog) {
-    return new DomainPropertyMatch().match(offer, requirement, errorLog);
+  private boolean semanticTypeMatch(String offer,
+                                    String requirement,
+                                    List<MatchingResultMessage> errorLog) {
+    return new SemanticTypeMatch().match(offer, requirement, errorLog);
   }
 
   private boolean datatypeMatch(String offer, String requirement,
diff --git a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/v2/PropertyMatch.java b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/v2/PropertyMatch.java
index ebbd28561e..ed0d4ec13f 100644
--- a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/v2/PropertyMatch.java
+++ b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/v2/PropertyMatch.java
@@ -59,7 +59,7 @@ public class PropertyMatch extends AbstractMatcher<EventProperty, EventProperty>
 
   private boolean isAnyProperty(EventProperty eventProperty) {
     return eventProperty instanceof EventPropertyPrimitive
-        && eventProperty.getDomainProperties() == null
+        && eventProperty.getSemanticType() == null
         && ((EventPropertyPrimitive) eventProperty).getMeasurementUnit() == null
         && ((EventPropertyPrimitive) eventProperty).getRuntimeType() == null;
   }
diff --git a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/v2/DomainPropertyMatch.java b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/v2/SemanticTypeMatch.java
similarity index 62%
rename from streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/v2/DomainPropertyMatch.java
rename to streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/v2/SemanticTypeMatch.java
index ce2518d2e2..d748e9fc63 100644
--- a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/v2/DomainPropertyMatch.java
+++ b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/v2/SemanticTypeMatch.java
@@ -22,22 +22,21 @@ import org.apache.streampipes.manager.matching.v2.utils.MatchingUtils;
 import org.apache.streampipes.model.client.matching.MatchingResultMessage;
 import org.apache.streampipes.model.client.matching.MatchingResultType;
 
-import java.net.URI;
 import java.util.List;
+import java.util.Objects;
 
-public class DomainPropertyMatch extends AbstractMatcher<List<URI>, List<URI>> {
+public class SemanticTypeMatch extends AbstractMatcher<String, String> {
 
-  public DomainPropertyMatch() {
-    super(MatchingResultType.DOMAIN_PROPERTY_MATCH);
+  public SemanticTypeMatch() {
+    super(MatchingResultType.SEMANTIC_TYPE_MATCH);
   }
 
   @Override
-  public boolean match(List<URI> offer, List<URI> requirement, List<MatchingResultMessage> errorLog) {
-    if (offer == null && ((requirement != null) && requirement.size() > 0)) {
+  public boolean match(String offer, String requirement, List<MatchingResultMessage> errorLog) {
+    if (offer == null && (requirement != null)) {
       return false;
     }
-    boolean match = MatchingUtils.nullCheck(offer, requirement)
-        || requirement.stream().allMatch(req -> offer.stream().anyMatch(of -> req.toString().equals(of.toString())));
+    boolean match = MatchingUtils.nullCheck(offer, requirement) || requirement.equalsIgnoreCase(offer);
 
     if (!match) {
       buildErrorMessage(errorLog, buildText(requirement));
@@ -45,12 +44,8 @@ public class DomainPropertyMatch extends AbstractMatcher<List<URI>, List<URI>> {
     return match;
   }
 
-  private String buildText(List<URI> requirement) {
-    if (requirement == null || requirement.size() == 0) {
-      return "-";
-    } else {
-      return requirement.get(0).toString();
-    }
+  private String buildText(String requirement) {
+    return Objects.requireNonNullElse(requirement, "-");
   }
 
 }
diff --git a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/remote/ContainerProvidedOptionsHandler.java b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/remote/ContainerProvidedOptionsHandler.java
index 16acbba678..eb212bb33e 100644
--- a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/remote/ContainerProvidedOptionsHandler.java
+++ b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/remote/ContainerProvidedOptionsHandler.java
@@ -30,6 +30,7 @@ import com.google.gson.JsonSyntaxException;
 import org.apache.http.client.fluent.Response;
 
 import java.io.IOException;
+import java.nio.charset.StandardCharsets;
 
 public class ContainerProvidedOptionsHandler {
 
@@ -49,7 +50,7 @@ public class ContainerProvidedOptionsHandler {
   }
 
   private RuntimeOptionsResponse handleResponse(Response httpResp) throws JsonSyntaxException, IOException {
-    String resp = httpResp.returnContent().asString();
+    String resp = httpResp.returnContent().asString(StandardCharsets.UTF_8);
     return JacksonSerializer.getObjectMapper().readValue(resp, RuntimeOptionsResponse.class);
   }
 
diff --git a/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/StaticProperties.java b/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/StaticProperties.java
index 2ad5f735e5..1793698efb 100644
--- a/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/StaticProperties.java
+++ b/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/StaticProperties.java
@@ -19,6 +19,7 @@
 package org.apache.streampipes.sdk;
 
 import org.apache.streampipes.model.schema.PropertyScope;
+import org.apache.streampipes.model.staticproperty.AnyStaticProperty;
 import org.apache.streampipes.model.staticproperty.CodeInputStaticProperty;
 import org.apache.streampipes.model.staticproperty.CollectionStaticProperty;
 import org.apache.streampipes.model.staticproperty.FileStaticProperty;
@@ -97,9 +98,9 @@ public class StaticProperties {
    * @return A configured FreeTextStaticProperty instance.
    */
   public static FreeTextStaticProperty stringFreeTextProperty(
-          Label label,
-          boolean isMultiLine,
-          boolean arePlaceholdersSupported) {
+      Label label,
+      boolean isMultiLine,
+      boolean arePlaceholdersSupported) {
     var property = stringFreeTextProperty(label);
     property.setMultiLine(isMultiLine);
     property.setPlaceholdersSupported(arePlaceholdersSupported);
@@ -233,6 +234,17 @@ public class StaticProperties {
     return osp;
   }
 
+  public static AnyStaticProperty multiValueSelection(Label label, List<Option> options) {
+    var osp = new AnyStaticProperty(
+        label.getInternalId(),
+        label.getLabel(),
+        label.getDescription()
+    );
+    osp.setOptions(options);
+
+    return osp;
+  }
+
   public static SecretStaticProperty secretValue(Label label) {
     return new SecretStaticProperty(label.getInternalId(),
         label.getLabel(), label.getDescription());
diff --git a/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/builder/PrimitivePropertyBuilder.java b/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/builder/PrimitivePropertyBuilder.java
index cdfaea0395..d313fe301d 100644
--- a/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/builder/PrimitivePropertyBuilder.java
+++ b/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/builder/PrimitivePropertyBuilder.java
@@ -25,7 +25,6 @@ import org.apache.streampipes.model.schema.QuantitativeValue;
 import org.apache.streampipes.sdk.utils.Datatypes;
 
 import java.net.URI;
-import java.util.Collections;
 import java.util.List;
 
 public class PrimitivePropertyBuilder {
@@ -53,12 +52,26 @@ public class PrimitivePropertyBuilder {
   /**
    * Specifies the semantics of the property (e.g., whether a double value stands for a latitude coordinate).
    *
-   * @param domainProperty The domain property as a String. The domain property should reflect an URI. Use some
+   * @param semanticType The semantic type as a String. Use some
    *                       existing vocabulary from {@link org.apache.streampipes.vocabulary} or create your own.
-   * @return
+   * @return PrimitivePropertyBuilder
+   */
+  public PrimitivePropertyBuilder semanticType(String semanticType) {
+    this.eventProperty.setSemanticType(semanticType);
+    return this;
+  }
+
+  /**
+   * @deprecated use {@link PrimitivePropertyBuilder#semanticType(String)} instead.
+   * Specifies the semantics of the property (e.g., whether a double value stands for a latitude coordinate).
+   *
+   * @param semanticType The semantic type as a String. Use some
+   *                       existing vocabulary from {@link org.apache.streampipes.vocabulary} or create your own.
+   * @return PrimitivePropertyBuilder
    */
-  public PrimitivePropertyBuilder domainProperty(String domainProperty) {
-    this.eventProperty.setDomainProperties(Collections.singletonList(URI.create(domainProperty)));
+  @Deprecated(forRemoval = true, since = "0.97.0")
+  public PrimitivePropertyBuilder domainProperty(String semanticType) {
+    this.eventProperty.setSemanticType(semanticType);
     return this;
   }
 
diff --git a/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/builder/PropertyRequirementsBuilder.java b/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/builder/PropertyRequirementsBuilder.java
index fed9a70db4..eecb6fbec0 100644
--- a/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/builder/PropertyRequirementsBuilder.java
+++ b/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/builder/PropertyRequirementsBuilder.java
@@ -22,8 +22,6 @@ import org.apache.streampipes.sdk.utils.Datatypes;
 import org.apache.streampipes.vocabulary.StreamPipes;
 
 import java.net.URI;
-import java.util.Arrays;
-import java.util.stream.Collectors;
 
 public class PropertyRequirementsBuilder {
 
@@ -57,15 +55,6 @@ public class PropertyRequirementsBuilder {
     return this;
   }
 
-  public PropertyRequirementsBuilder domainPropertyReq(String... domainProperties) {
-    this.propertyReq.setDomainProperties(Arrays
-        .stream(domainProperties)
-        .map(URI::create)
-        .collect(Collectors.toList()));
-
-    return this;
-  }
-
   public PropertyRequirementsBuilder measurementUnitReq(String measurementUnit) {
     this.propertyReq.setMeasurementUnit(URI.create(measurementUnit));
     return this;
diff --git a/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/extractor/AbstractParameterExtractor.java b/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/extractor/AbstractParameterExtractor.java
index b7230510f3..844f26af2c 100644
--- a/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/extractor/AbstractParameterExtractor.java
+++ b/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/extractor/AbstractParameterExtractor.java
@@ -62,7 +62,7 @@ public abstract class AbstractParameterExtractor<T extends InvocableStreamPipesE
     implements IParameterExtractor {
 
   protected T sepaElement;
-  private TypeParser typeParser;
+  private final TypeParser typeParser;
 
   public AbstractParameterExtractor(T sepaElement) {
     this.sepaElement = sepaElement;
@@ -246,6 +246,17 @@ public abstract class AbstractParameterExtractor<T extends InvocableStreamPipesE
         .collect(Collectors.toList());
   }
 
+  @Override
+  public <V> List<V> selectedMultiValuesInternalNames(String internalName, Class<V> targetClass) {
+    return getStaticPropertyByName(internalName, AnyStaticProperty.class)
+        .getOptions()
+        .stream()
+        .filter(Option::isSelected)
+        .map(Option::getInternalName)
+        .map(o -> typeParser.parse(o, targetClass))
+        .collect(Collectors.toList());
+  }
+
   @Override
   /**
    * Extracts the user configuration from the tree static property.
@@ -666,4 +677,13 @@ public abstract class AbstractParameterExtractor<T extends InvocableStreamPipesE
                                                        .equals(scope.name()))
         .collect(Collectors.toList());
   }
+
+  @Override
+  public List<EventProperty> getInputEventProperties(int streamIndex) {
+    if (!sepaElement.getInputStreams().isEmpty()) {
+      return sepaElement.getInputStreams().get(streamIndex).getEventSchema().getEventProperties();
+    } else {
+      return List.of();
+    }
+  }
 }
diff --git a/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/helpers/EpProperties.java b/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/helpers/EpProperties.java
index ced0dd00e9..a17247a2f3 100644
--- a/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/helpers/EpProperties.java
+++ b/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/helpers/EpProperties.java
@@ -18,7 +18,6 @@
 
 package org.apache.streampipes.sdk.helpers;
 
-import org.apache.streampipes.commons.Utils;
 import org.apache.streampipes.model.schema.Enumeration;
 import org.apache.streampipes.model.schema.EventProperty;
 import org.apache.streampipes.model.schema.EventPropertyList;
@@ -58,9 +57,9 @@ public class EpProperties {
   }
 
   public static EventPropertyList listNestedEp(Label label, String runtimeName, String
-      domainProperty, List<EventProperty> listItemProperties) {
+      semanticType, List<EventProperty> listItemProperties) {
     EventPropertyList list = listNestedEp(label, runtimeName, listItemProperties);
-    list.setDomainProperties(Arrays.asList(URI.create(domainProperty)));
+    list.setSemanticType(semanticType);
     return list;
   }
 
@@ -190,9 +189,8 @@ public class EpProperties {
    * @return {@link org.apache.streampipes.model.schema.EventPropertyList}
    */
   public static EventPropertyList listEp(Label label, String runtimeName, EventProperty eventProperty,
-                                         String domainProperty) {
-    return getPreparedProperty(label, new EventPropertyList(runtimeName, eventProperty, Utils.createURI
-        (domainProperty)));
+                                         String semanticType) {
+    return getPreparedProperty(label, new EventPropertyList(runtimeName, eventProperty, semanticType));
   }
 
   /**
@@ -287,25 +285,26 @@ public class EpProperties {
    * Creates a new primitive property of type integer and the provided domain property.
    *
    * @param runtimeName    The field identifier of the event property at runtime.
-   * @param domainProperty The semantics of the list property as a String. The string should correspond to a URI
-   *                       provided by a vocabulary. Use one of the vocabularies provided in
+   * @param semanticType The semantics of the list property as a String. Use one of the vocabularies provided in
    *                       {@link org.apache.streampipes.vocabulary} or create your own domain-specific vocabulary.
    * @return {@link org.apache.streampipes.model.schema.EventPropertyPrimitive}
    */
-  public static EventPropertyPrimitive integerEp(Label label, String runtimeName, String domainProperty) {
-    return ep(label, XSD.INTEGER.toString(), runtimeName, domainProperty);
+  public static EventPropertyPrimitive integerEp(Label label, String runtimeName, String semanticType) {
+    return ep(label, XSD.INTEGER.toString(), runtimeName, semanticType);
   }
 
   /**
    * Creates a new primitive property of type integer and the provided domain properties. In addition, the value range
    * of the property is restricted to the defined {@link org.apache.streampipes.model.schema.Enumeration}
    *
+   * @deprecated provide the semantic type as string
    * @param runtimeName      The field identifier of the event property at runtime.
    * @param domainProperties The semantics of the list property as a list of URIs. Use one of the vocabularies
    *                         provided in
    *                         {@link org.apache.streampipes.vocabulary} or create your own domain-specific vocabulary.
    * @return {@link org.apache.streampipes.model.schema.EventPropertyPrimitive}
    */
+  @Deprecated(forRemoval = true, since = "0.97.0")
   public static EventPropertyPrimitive integerEp(Label label, String runtimeName, List<URI> domainProperties) {
     return ep(label, XSD.INTEGER.toString(), runtimeName, domainProperties);
   }
@@ -317,15 +316,15 @@ public class EpProperties {
    *                       If you do not want to have a label besides the runtime name, use
    *                       {@link org.apache.streampipes.sdk.helpers.Labels}
    * @param runtimeName    The field identifier of the event property at runtime.
-   * @param domainProperty The semantics of the list property as a String. The string should correspond to a URI
-   *                       provided by a vocabulary. Use one of the vocabularies provided in
+   * @param semanticType The semantics of the list property as a String. Use one of the vocabularies provided in
    *                       {@link org.apache.streampipes.vocabulary} or create your own domain-specific vocabulary.
    * @return {@link org.apache.streampipes.model.schema.EventPropertyPrimitive}
    */
-  public static EventPropertyPrimitive longEp(Label label, String runtimeName, String domainProperty) {
-    return ep(label, XSD.LONG.toString(), runtimeName, domainProperty);
+  public static EventPropertyPrimitive longEp(Label label, String runtimeName, String semanticType) {
+    return ep(label, XSD.LONG.toString(), runtimeName, semanticType);
   }
 
+  @Deprecated(forRemoval = true, since = "0.97.0")
   public static EventPropertyPrimitive longEp(Label label, String runtimeName, List<URI> domainProperties) {
     return ep(label, XSD.LONG.toString(), runtimeName, domainProperties);
   }
@@ -353,14 +352,18 @@ public class EpProperties {
     return ep;
   }
 
-  public static EventPropertyPrimitive ep(Label label, String runtimeType, String runtimeName, String domainProperty) {
-    return getPreparedProperty(label, new EventPropertyPrimitive(runtimeType, runtimeName, "", Utils.createURI
-        (domainProperty)));
+  public static EventPropertyPrimitive ep(Label label,
+                                          String runtimeType,
+                                          String runtimeName,
+                                          String semanticType) {
+    return getPreparedProperty(label, new EventPropertyPrimitive(runtimeType, runtimeName, "", semanticType));
   }
 
+  @Deprecated(forRemoval = true, since = "0.97.0")
   private static EventPropertyPrimitive ep(Label label, String runtimeType, String runtimeName, List<URI>
       domainProperties) {
-    return getPreparedProperty(label, new EventPropertyPrimitive(runtimeType, runtimeName, "", domainProperties));
+    String semanticType = domainProperties.isEmpty() ? null : domainProperties.get(0).toString();
+    return getPreparedProperty(label, new EventPropertyPrimitive(runtimeType, runtimeName, "", semanticType));
   }
 
   private static <T extends EventProperty> T getPreparedProperty(Label label, T eventProperty) {
diff --git a/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/helpers/EpRequirements.java b/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/helpers/EpRequirements.java
index 1d310fcb8e..77afed7fe7 100644
--- a/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/helpers/EpRequirements.java
+++ b/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/helpers/EpRequirements.java
@@ -18,7 +18,6 @@
 
 package org.apache.streampipes.sdk.helpers;
 
-import org.apache.streampipes.commons.Utils;
 import org.apache.streampipes.model.schema.EventProperty;
 import org.apache.streampipes.model.schema.EventPropertyList;
 import org.apache.streampipes.model.schema.EventPropertyNested;
@@ -124,28 +123,48 @@ public class EpRequirements {
     return appendDomainProperty(datatypeReq(SO.NUMBER), domainProperty);
   }
 
-  private static <T extends EventProperty> EventProperty domainPropertyReq(String domainProperty,
-                                                                           Class<T> eventProperty) {
+  private static <T extends EventProperty> EventProperty semanticTypeReq(String semanticType,
+                                                                         Class<T> eventProperty) {
     EventProperty ep = null;
     try {
       ep = eventProperty.newInstance();
+      ep.setSemanticType(semanticType);
     } catch (InstantiationException | IllegalAccessException e) {
       e.printStackTrace();
     }
-    ep.setDomainProperties(Utils.createURI(domainProperty));
     return ep;
   }
 
+  public static EventPropertyPrimitive semanticTypeReq(String semanticType) {
+    return (EventPropertyPrimitive) semanticTypeReq(semanticType, EventPropertyPrimitive.class);
+  }
+
+  public static EventPropertyList semanticTypeReqList(String semanticType) {
+    return (EventPropertyList) semanticTypeReq(semanticType, EventPropertyList.class);
+  }
+
+  /**
+   * @param domainProperty the semantic type
+   * @return EventPropertyPrimitive
+   * @deprecated Use {@link EpRequirements#semanticTypeReq(String)} instead
+   */
+  @Deprecated(forRemoval = true, since = "0.97.0")
   public static EventPropertyPrimitive domainPropertyReq(String domainProperty) {
-    return (EventPropertyPrimitive) domainPropertyReq(domainProperty, EventPropertyPrimitive.class);
+    return (EventPropertyPrimitive) semanticTypeReq(domainProperty, EventPropertyPrimitive.class);
   }
 
+  /**
+   * @param domainProperty the semantic type
+   * @return EventPropertyList
+   * @deprecated Use {@link EpRequirements#semanticTypeReqList(String)} instead
+   */
+  @Deprecated(forRemoval = true, since = "0.97.0")
   public static EventPropertyList domainPropertyReqList(String domainProperty) {
-    return (EventPropertyList) domainPropertyReq(domainProperty, EventPropertyList.class);
+    return (EventPropertyList) semanticTypeReq(domainProperty, EventPropertyList.class);
   }
 
-  private static EventPropertyPrimitive appendDomainProperty(EventPropertyPrimitive property, String domainProperty) {
-    property.setDomainProperties(Utils.createURI(domainProperty));
+  private static EventPropertyPrimitive appendDomainProperty(EventPropertyPrimitive property, String semanticType) {
+    property.setSemanticType(semanticType);
     return property;
   }
 
diff --git a/streampipes-service-extensions/src/main/java/org/apache/streampipes/service/extensions/function/StreamPipesFunctionHandler.java b/streampipes-service-extensions/src/main/java/org/apache/streampipes/service/extensions/function/StreamPipesFunctionHandler.java
index aeda204da9..a36d788a4d 100644
--- a/streampipes-service-extensions/src/main/java/org/apache/streampipes/service/extensions/function/StreamPipesFunctionHandler.java
+++ b/streampipes-service-extensions/src/main/java/org/apache/streampipes/service/extensions/function/StreamPipesFunctionHandler.java
@@ -62,27 +62,32 @@ public enum StreamPipesFunctionHandler {
     var client = new StreamPipesClientResolver().makeStreamPipesClientInstance();
     functions.forEach(function -> {
       function.getFunctionConfig().getOutputDataStreams().values().forEach(ds -> {
-        DeclarersSingleton.getInstance().add(new IStreamPipesDataStream() {
-          @Override
-          public IDataStreamConfiguration declareConfig() {
-            return DataStreamConfiguration.create(
-                () -> this,
-                ds
-            );
+        if (!DeclarersSingleton.getInstance().getDataStreams().containsKey(ds.getAppId())) {
+          DeclarersSingleton.getInstance().add(new IStreamPipesDataStream() {
+            @Override
+            public IDataStreamConfiguration declareConfig() {
+              return DataStreamConfiguration.create(
+                  () -> this,
+                  ds
+              );
+            }
+
+            @Override
+            public void executeStream() {
+
+            }
+
+            @Override
+            public boolean isExecutable() {
+              return false;
+            }
+          });
+          if (client.streams().get(ds.getElementId()).isEmpty()) {
+            client.streams().create(ds);
+          } else {
+            client.streams().update(ds);
           }
-
-          @Override
-          public void executeStream() {
-
-          }
-
-          @Override
-          public boolean isExecutable() {
-            return false;
-          }
-        });
-
-        client.streams().create(ds);
+        }
       });
     });
   }
@@ -91,7 +96,7 @@ public enum StreamPipesFunctionHandler {
     this.runningInstances.forEach((key, value) -> {
       value.discardRuntime();
     });
-    new Thread(new FunctionDeregistrationHandler(getFunctionDefinitions())).start();
+    new FunctionDeregistrationHandler(getFunctionDefinitions()).run();
   }
 
   private List<FunctionDefinition> getFunctionDefinitions() {
diff --git a/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/serializer/EventPropertySerializer.java b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/serializer/EventPropertySerializer.java
new file mode 100644
index 0000000000..30e04cd69c
--- /dev/null
+++ b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/serializer/EventPropertySerializer.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.storage.couchdb.serializer;
+
+import org.apache.streampipes.model.schema.EventProperty;
+
+import com.google.gson.JsonDeserializationContext;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParseException;
+import com.google.gson.JsonPrimitive;
+
+import java.lang.reflect.Type;
+
+public class EventPropertySerializer extends CouchDbJsonSerializer<EventProperty> {
+
+  private static final String DomainProperties = "domainProperties";
+
+  @Override
+  public EventProperty deserialize(JsonElement json,
+                                   Type typeOfT,
+                                   JsonDeserializationContext context) throws JsonParseException {
+
+    JsonObject jsonObject = json.getAsJsonObject();
+    String type = jsonObject.get("type").getAsString();
+    JsonElement element = jsonObject.get("properties");
+    if (element.getAsJsonObject().has(DomainProperties)) {
+      var domainProperties = element.getAsJsonObject().get(DomainProperties).getAsJsonArray();
+      if (!domainProperties.isEmpty()) {
+        element.getAsJsonObject().add("semanticType", new JsonPrimitive(domainProperties.get(0).getAsString()));
+      }
+      element.getAsJsonObject().remove(DomainProperties);
+
+    }
+
+    try {
+      return context.deserialize(element, Class.forName(type));
+    } catch (ClassNotFoundException cnfe) {
+      throw new JsonParseException("Unknown element type: " + type, cnfe);
+    }
+  }
+}
diff --git a/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/serializer/GsonSerializer.java b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/serializer/GsonSerializer.java
index 37a2293ff4..685db7ee03 100644
--- a/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/serializer/GsonSerializer.java
+++ b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/serializer/GsonSerializer.java
@@ -75,7 +75,7 @@ public class GsonSerializer {
 
   public static GsonBuilder getGsonBuilder() {
     GsonBuilder builder = new GsonBuilder();
-    builder.registerTypeAdapter(EventProperty.class, new CouchDbJsonSerializer<EventProperty>());
+    builder.registerTypeAdapter(EventProperty.class, new EventPropertySerializer());
     builder.registerTypeAdapter(StaticProperty.class, new CouchDbJsonSerializer<StaticProperty>());
     builder.registerTypeAdapter(OutputStrategy.class, new CouchDbJsonSerializer<OutputStrategy>());
     builder.registerTypeAdapter(TransportProtocol.class, new CouchDbJsonSerializer<TransportProtocol>());
diff --git a/ui/.lintstagedrc.json b/ui/.lintstagedrc.json
index 059fea6ac0..ca7497c491 100644
--- a/ui/.lintstagedrc.json
+++ b/ui/.lintstagedrc.json
@@ -1,4 +1,4 @@
 {
-  "src/**/*.ts": "prettier --write",
-  "src/**/*.ts": ["ng-lint-staged lint --fix"]
+  "*.*": "prettier --check",
+  "src/**/*.ts": ["ng-lint-staged lint --"]
 }
diff --git a/ui/cypress/support/utils/datalake/DataLakeUtils.ts b/ui/cypress/support/utils/datalake/DataLakeUtils.ts
index de72c60baa..664c2ccd1c 100644
--- a/ui/cypress/support/utils/datalake/DataLakeUtils.ts
+++ b/ui/cypress/support/utils/datalake/DataLakeUtils.ts
@@ -91,7 +91,7 @@ export class DataLakeUtils {
         widgetType: string,
     ) {
         DataLakeUtils.goToDatalake();
-        DataLakeUtils.createAndEditDataView(dataViewName);
+        DataLakeUtils.createAndEditDataView();
 
         DataLakeUtils.selectTimeRange(
             new Date(2020, 10, 20, 22, 44),
@@ -162,7 +162,7 @@ export class DataLakeUtils {
 
     public static createAndEditDataView() {
         // Create new data view
-        cy.dataCy('open-new-data-view').click();
+        cy.dataCy('open-new-data-view', { timeout: 10000 }).click();
     }
 
     public static removeWidget(dataViewName: string) {
@@ -425,7 +425,7 @@ export class DataLakeUtils {
     }
 
     public static openTimeSelectorMenu() {
-        cy.dataCy('time-selector-menu').click();
+        cy.dataCy('time-selector-menu', { timeout: 10000 }).click();
     }
 
     public static applyCustomTimeSelection() {
diff --git a/ui/deployment/modules.yml b/ui/deployment/modules.yml
index 44bf959acf..b9c929780a 100644
--- a/ui/deployment/modules.yml
+++ b/ui/deployment/modules.yml
@@ -83,7 +83,7 @@ spConfiguration:
     description: 'In the configuration module, basic StreamPipes settings and services can be configured.'
     icon: 'settings'
     pageNames: 'PageName.SETTINGS'
-    privileges: '[UserPrivilege.PRIVILEGE_WRITE_ASSETS, UserPrivilege.PRIVILEGE_WRITE_LABELS, UserPrivilege.PRIVILEGE_READ_FILES, UserPrivilege.PRIVILEGE_WRITE_FILES]'
+    privileges: '[UserPrivilege.PRIVILEGE_WRITE_ASSETS, UserPrivilege.PRIVILEGE_WRITE_LABELS, UserPrivilege.PRIVILEGE_WRITE_FILES]'
     showStatusBox: false
 spAppOverview:
     componentImport: False
diff --git a/ui/package-lock.json b/ui/package-lock.json
index faee36b4ce..054742cf18 100644
--- a/ui/package-lock.json
+++ b/ui/package-lock.json
@@ -7461,9 +7461,9 @@
       "dev": true
     },
     "node_modules/body-parser": {
-      "version": "1.20.2",
-      "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz",
-      "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==",
+      "version": "1.20.3",
+      "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz",
+      "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==",
       "dev": true,
       "dependencies": {
         "bytes": "3.1.2",
@@ -7474,7 +7474,7 @@
         "http-errors": "2.0.0",
         "iconv-lite": "0.4.24",
         "on-finished": "2.4.1",
-        "qs": "6.11.0",
+        "qs": "6.13.0",
         "raw-body": "2.5.2",
         "type-is": "~1.6.18",
         "unpipe": "1.0.0"
@@ -7512,12 +7512,12 @@
       }
     },
     "node_modules/body-parser/node_modules/qs": {
-      "version": "6.11.0",
-      "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
-      "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
+      "version": "6.13.0",
+      "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz",
+      "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==",
       "dev": true,
       "dependencies": {
-        "side-channel": "^1.0.4"
+        "side-channel": "^1.0.6"
       },
       "engines": {
         "node": ">=0.6"
@@ -10951,37 +10951,37 @@
       "dev": true
     },
     "node_modules/express": {
-      "version": "4.19.2",
-      "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz",
-      "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==",
+      "version": "4.21.0",
+      "resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz",
+      "integrity": "sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==",
       "dev": true,
       "dependencies": {
         "accepts": "~1.3.8",
         "array-flatten": "1.1.1",
-        "body-parser": "1.20.2",
+        "body-parser": "1.20.3",
         "content-disposition": "0.5.4",
         "content-type": "~1.0.4",
         "cookie": "0.6.0",
         "cookie-signature": "1.0.6",
         "debug": "2.6.9",
         "depd": "2.0.0",
-        "encodeurl": "~1.0.2",
+        "encodeurl": "~2.0.0",
         "escape-html": "~1.0.3",
         "etag": "~1.8.1",
-        "finalhandler": "1.2.0",
+        "finalhandler": "1.3.1",
         "fresh": "0.5.2",
         "http-errors": "2.0.0",
-        "merge-descriptors": "1.0.1",
+        "merge-descriptors": "1.0.3",
         "methods": "~1.1.2",
         "on-finished": "2.4.1",
         "parseurl": "~1.3.3",
-        "path-to-regexp": "0.1.7",
+        "path-to-regexp": "0.1.10",
         "proxy-addr": "~2.0.7",
-        "qs": "6.11.0",
+        "qs": "6.13.0",
         "range-parser": "~1.2.1",
         "safe-buffer": "5.2.1",
-        "send": "0.18.0",
-        "serve-static": "1.15.0",
+        "send": "0.19.0",
+        "serve-static": "1.16.2",
         "setprototypeof": "1.2.0",
         "statuses": "2.0.1",
         "type-is": "~1.6.18",
@@ -11010,14 +11010,23 @@
         "ms": "2.0.0"
       }
     },
+    "node_modules/express/node_modules/encodeurl": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
+      "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
     "node_modules/express/node_modules/finalhandler": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
-      "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==",
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz",
+      "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==",
       "dev": true,
       "dependencies": {
         "debug": "2.6.9",
-        "encodeurl": "~1.0.2",
+        "encodeurl": "~2.0.0",
         "escape-html": "~1.0.3",
         "on-finished": "2.4.1",
         "parseurl": "~1.3.3",
@@ -11059,12 +11068,12 @@
       }
     },
     "node_modules/express/node_modules/qs": {
-      "version": "6.11.0",
-      "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
-      "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
+      "version": "6.13.0",
+      "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz",
+      "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==",
       "dev": true,
       "dependencies": {
-        "side-channel": "^1.0.4"
+        "side-channel": "^1.0.6"
       },
       "engines": {
         "node": ">=0.6"
@@ -11074,9 +11083,9 @@
       }
     },
     "node_modules/express/node_modules/send": {
-      "version": "0.18.0",
-      "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
-      "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==",
+      "version": "0.19.0",
+      "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz",
+      "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==",
       "dev": true,
       "dependencies": {
         "debug": "2.6.9",
@@ -11097,6 +11106,15 @@
         "node": ">= 0.8.0"
       }
     },
+    "node_modules/express/node_modules/send/node_modules/encodeurl": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
+      "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
     "node_modules/express/node_modules/send/node_modules/ms": {
       "version": "2.1.3",
       "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
@@ -11104,15 +11122,15 @@
       "dev": true
     },
     "node_modules/express/node_modules/serve-static": {
-      "version": "1.15.0",
-      "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz",
-      "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==",
+      "version": "1.16.2",
+      "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz",
+      "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==",
       "dev": true,
       "dependencies": {
-        "encodeurl": "~1.0.2",
+        "encodeurl": "~2.0.0",
         "escape-html": "~1.0.3",
         "parseurl": "~1.3.3",
-        "send": "0.18.0"
+        "send": "0.19.0"
       },
       "engines": {
         "node": ">= 0.8.0"
@@ -14962,10 +14980,13 @@
       }
     },
     "node_modules/merge-descriptors": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
-      "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==",
-      "dev": true
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz",
+      "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==",
+      "dev": true,
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
     },
     "node_modules/merge-stream": {
       "version": "2.0.0",
@@ -17639,9 +17660,9 @@
       }
     },
     "node_modules/path-to-regexp": {
-      "version": "0.1.7",
-      "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
-      "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==",
+      "version": "0.1.10",
+      "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz",
+      "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==",
       "dev": true
     },
     "node_modules/path-type": {
diff --git a/ui/projects/streampipes/platform-services/src/lib/model/dashboard/dashboard.model.ts b/ui/projects/streampipes/platform-services/src/lib/model/dashboard/dashboard.model.ts
index 8a65f934ed..532a19b2d4 100644
--- a/ui/projects/streampipes/platform-services/src/lib/model/dashboard/dashboard.model.ts
+++ b/ui/projects/streampipes/platform-services/src/lib/model/dashboard/dashboard.model.ts
@@ -25,6 +25,7 @@ export interface DashboardConfig extends GridsterConfig {}
 export interface ClientDashboardItem extends GridsterItem {
     widgetId: string;
     widgetType: string;
+    timeSettings?: TimeSettings;
     id: string;
 }
 
diff --git a/ui/projects/streampipes/platform-services/src/lib/model/datalake/DateRange.ts b/ui/projects/streampipes/platform-services/src/lib/model/datalake/DateRange.ts
index 6c305f6dd4..9f3cff7d29 100644
--- a/ui/projects/streampipes/platform-services/src/lib/model/datalake/DateRange.ts
+++ b/ui/projects/streampipes/platform-services/src/lib/model/datalake/DateRange.ts
@@ -24,6 +24,11 @@ export interface TimeSettings {
     timeSelectionId?: TimeSelectionId;
 }
 
+export interface WidgetTimeSettings {
+    timeSettings: TimeSettings;
+    widgetIndex?: number;
+}
+
 export interface TimeString {
     startDate: string;
     startTime: string;
diff --git a/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model.ts b/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model.ts
index 7c9650ec20..1ae8e4e32d 100644
--- a/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model.ts
+++ b/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model.ts
@@ -20,7 +20,7 @@
 /* tslint:disable */
 /* eslint-disable */
 // @ts-nocheck
-// Generated using typescript-generator version 3.2.1263 on 2024-09-10 17:11:03.
+// Generated using typescript-generator version 3.2.1263 on 2024-09-30 14:11:40.
 
 export class NamedStreamPipesEntity implements Storable {
     '@class':
@@ -970,6 +970,7 @@ export class DashboardItem {
     name: string;
     rows: number;
     settings: string[];
+    timeSettings: { [index: string]: any };
     x: number;
     y: number;
 
@@ -989,6 +990,9 @@ export class DashboardItem {
         instance.settings = __getCopyArrayFn(__identity<string>())(
             data.settings,
         );
+        instance.timeSettings = __getCopyObjectFn(__identity<any>())(
+            data.timeSettings,
+        );
         instance.x = data.x;
         instance.y = data.y;
         return instance;
@@ -1480,12 +1484,12 @@ export class EventProperty {
         | 'org.apache.streampipes.model.schema.EventPropertyPrimitive';
     'additionalMetadata': { [index: string]: any };
     'description': string;
-    'domainProperties': string[];
     'elementId': string;
     'label': string;
     'propertyScope': string;
     'runtimeId': string;
     'runtimeName': string;
+    'semanticType': string;
 
     static 'fromData'(
         data: EventProperty,
@@ -1500,14 +1504,12 @@ export class EventProperty {
             data.additionalMetadata,
         );
         instance.description = data.description;
-        instance.domainProperties = __getCopyArrayFn(__identity<string>())(
-            data.domainProperties,
-        );
         instance.elementId = data.elementId;
         instance.label = data.label;
         instance.propertyScope = data.propertyScope;
         instance.runtimeId = data.runtimeId;
         instance.runtimeName = data.runtimeName;
+        instance.semanticType = data.semanticType;
         return instance;
     }
 
diff --git a/ui/projects/streampipes/platform-services/src/lib/model/types/semantic-type.ts b/ui/projects/streampipes/platform-services/src/lib/model/types/semantic-type.ts
index e0aff4fb37..e4869422e2 100644
--- a/ui/projects/streampipes/platform-services/src/lib/model/types/semantic-type.ts
+++ b/ui/projects/streampipes/platform-services/src/lib/model/types/semantic-type.ts
@@ -42,14 +42,24 @@ export class SemanticType {
     }
 
     public static isTimestamp(property: EventProperty): boolean {
-        return property.domainProperties.includes(SemanticType.TIMESTAMP);
+        return this.equalsIgnoreCase(
+            SemanticType.TIMESTAMP,
+            property.semanticType,
+        );
     }
 
     public static isImage(property: EventProperty): boolean {
-        return property.domainProperties.includes(SemanticType.IMAGE);
+        return this.equalsIgnoreCase(SemanticType.IMAGE, property.semanticType);
     }
 
     public static isNumber(property: EventProperty): boolean {
-        return property.domainProperties.includes(SemanticType.SO_NUMBER);
+        return this.equalsIgnoreCase(
+            SemanticType.SO_NUMBER,
+            property.semanticType,
+        );
+    }
+
+    public static equalsIgnoreCase(str1: string, str2: string): boolean {
+        return str1?.toLowerCase() === str2?.toLowerCase();
     }
 }
diff --git a/ui/src/app/assets/components/asset-overview/asset-overview.component.ts b/ui/src/app/assets/components/asset-overview/asset-overview.component.ts
index 386a03157d..0caf6b79c6 100644
--- a/ui/src/app/assets/components/asset-overview/asset-overview.component.ts
+++ b/ui/src/app/assets/components/asset-overview/asset-overview.component.ts
@@ -24,6 +24,7 @@ import {
     SpAssetModel,
 } from '@streampipes/platform-services';
 import {
+    ConfirmDialogComponent,
     CurrentUserService,
     DialogService,
     PanelType,
@@ -35,6 +36,7 @@ import { Router } from '@angular/router';
 import { SpCreateAssetDialogComponent } from '../../dialog/create-asset/create-asset-dialog.component';
 import { IdGeneratorService } from '../../../core-services/id-generator/id-generator.service';
 import { UserPrivilege } from '../../../_enums/user-privilege.enum';
+import { MatDialog } from '@angular/material/dialog';
 
 @Component({
     selector: 'sp-asset-overview',
@@ -59,6 +61,7 @@ export class SpAssetOverviewComponent implements OnInit {
         private idGeneratorService: IdGeneratorService,
         private assetBrowserService: SpAssetBrowserService,
         private currentUserService: CurrentUserService,
+        private dialog: MatDialog,
     ) {}
 
     ngOnInit(): void {
@@ -118,15 +121,29 @@ export class SpAssetOverviewComponent implements OnInit {
     }
 
     deleteAsset(asset: SpAssetModel) {
-        this.genericStorageService
-            .deleteDocument(
-                AssetConstants.ASSET_APP_DOC_NAME,
-                asset._id,
-                asset._rev,
-            )
-            .subscribe(() => {
-                this.loadAssets();
-                this.assetBrowserService.loadAssetData();
-            });
+        const dialogRef = this.dialog.open(ConfirmDialogComponent, {
+            width: '500px',
+            data: {
+                title: 'Are you sure you want to delete this asset?',
+                subtitle: 'This action cannot be reversed!',
+                cancelTitle: 'Cancel',
+                okTitle: 'Delete Asset',
+                confirmAndCancel: true,
+            },
+        });
+        dialogRef.afterClosed().subscribe(result => {
+            if (result) {
+                this.genericStorageService
+                    .deleteDocument(
+                        AssetConstants.ASSET_APP_DOC_NAME,
+                        asset._id,
+                        asset._rev,
+                    )
+                    .subscribe(() => {
+                        this.loadAssets();
+                        this.assetBrowserService.loadAssetData();
+                    });
+            }
+        });
     }
 }
diff --git a/ui/src/app/configuration/configuration-tabs.service.ts b/ui/src/app/configuration/configuration-tabs.service.ts
index dc1187b0aa..fa2a384671 100644
--- a/ui/src/app/configuration/configuration-tabs.service.ts
+++ b/ui/src/app/configuration/configuration-tabs.service.ts
@@ -57,7 +57,7 @@ export class SpConfigurationTabsService {
             itemId: 'files',
             itemTitle: 'Files',
             itemLink: ['configuration', 'files'],
-            roles: ['PRIVILEGE_READ_FILES', 'PRIVILEGE_WRITE_FILES'],
+            roles: ['PRIVILEGE_WRITE_FILES'],
         },
         {
             itemId: 'labels',
diff --git a/ui/src/app/connect/components/adapter-configuration/schema-editor/event-property-row/event-property-row.component.ts b/ui/src/app/connect/components/adapter-configuration/schema-editor/event-property-row/event-property-row.component.ts
index 93e776b6ec..59c01ae599 100644
--- a/ui/src/app/connect/components/adapter-configuration/schema-editor/event-property-row/event-property-row.component.ts
+++ b/ui/src/app/connect/components/adapter-configuration/schema-editor/event-property-row/event-property-row.component.ts
@@ -159,10 +159,7 @@ export class EventPropertyRowComponent implements OnInit {
     }
 
     isTimestampProperty(node) {
-        if (
-            node.domainProperties &&
-            node.domainProperties.some(dp => dp === SemanticType.TIMESTAMP)
-        ) {
+        if (node.semanticType !== undefined && SemanticType.isTimestamp(node)) {
             node.runtimeType = DataType.LONG;
             return true;
         } else {
diff --git a/ui/src/app/connect/components/adapter-configuration/schema-editor/event-schema/event-schema.component.ts b/ui/src/app/connect/components/adapter-configuration/schema-editor/event-schema/event-schema.component.ts
index 09423c2d32..da1b6c5a54 100644
--- a/ui/src/app/connect/components/adapter-configuration/schema-editor/event-schema/event-schema.component.ts
+++ b/ui/src/app/connect/components/adapter-configuration/schema-editor/event-schema/event-schema.component.ts
@@ -211,7 +211,7 @@ export class EventSchemaComponent implements OnChanges {
 
         eventProperty.runtimeName = runtimeName;
         eventProperty.runtimeType = DataType.STRING;
-        eventProperty.domainProperties = [];
+        eventProperty.semanticType = undefined;
         eventProperty.propertyScope = 'DIMENSION_PROPERTY';
         eventProperty.additionalMetadata = {};
 
@@ -230,7 +230,7 @@ export class EventSchemaComponent implements OnChanges {
         eventProperty.runtimeName = 'timestamp';
         eventProperty.label = 'Timestamp';
         eventProperty.description = 'The current timestamp value';
-        eventProperty.domainProperties = [SemanticType.TIMESTAMP];
+        eventProperty.semanticType = SemanticType.TIMESTAMP;
         eventProperty.propertyScope = 'HEADER_PROPERTY';
         eventProperty.runtimeType = DataType.LONG;
         eventProperty.additionalMetadata = {};
@@ -280,7 +280,7 @@ export class EventSchemaComponent implements OnChanges {
     private checkIfValid(eventSchema: EventSchema): boolean {
         this.timestampPresent = false;
         eventSchema.eventProperties.forEach(p => {
-            if (p.domainProperties.indexOf('http://schema.org/DateTime') > -1) {
+            if (SemanticType.isTimestamp(p)) {
                 this.timestampPresent = true;
             }
         });
diff --git a/ui/src/app/connect/dialog/edit-event-property/components/edit-schema-transformation/edit-schema-transformation.component.html b/ui/src/app/connect/dialog/edit-event-property/components/edit-schema-transformation/edit-schema-transformation.component.html
index 84732adcc3..4b6801488b 100644
--- a/ui/src/app/connect/dialog/edit-event-property/components/edit-schema-transformation/edit-schema-transformation.component.html
+++ b/ui/src/app/connect/dialog/edit-event-property/components/edit-schema-transformation/edit-schema-transformation.component.html
@@ -67,7 +67,7 @@
                     class="dmainProperty"
                     name="domainproperty"
                     id="domainproperty"
-                    [(ngModel)]="cachedProperty.domainProperties[0]"
+                    [(ngModel)]="cachedProperty.semanticType"
                     [matAutocomplete]="st"
                     [disabled]="isTimestampProperty"
                     [matAutocompleteDisabled]="isTimestampProperty"
diff --git a/ui/src/app/connect/dialog/edit-event-property/components/edit-schema-transformation/edit-schema-transformation.component.ts b/ui/src/app/connect/dialog/edit-event-property/components/edit-schema-transformation/edit-schema-transformation.component.ts
index 7c262a8e2f..4644e33e10 100644
--- a/ui/src/app/connect/dialog/edit-event-property/components/edit-schema-transformation/edit-schema-transformation.component.ts
+++ b/ui/src/app/connect/dialog/edit-event-property/components/edit-schema-transformation/edit-schema-transformation.component.ts
@@ -28,6 +28,8 @@ import { Observable } from 'rxjs';
 import { ShepherdService } from '../../../../../services/tour/shepherd.service';
 import {
     DataType,
+    EventPropertyPrimitive,
+    EventPropertyUnion,
     SemanticType,
     SemanticTypesRestService,
 } from '@streampipes/platform-services';
@@ -40,7 +42,7 @@ import { Router } from '@angular/router';
 })
 export class EditSchemaTransformationComponent implements OnInit {
     @Input()
-    cachedProperty: any;
+    cachedProperty: EventPropertyUnion;
 
     @Input() isTimestampProperty: boolean;
     @Input() isNestedProperty: boolean;
@@ -79,11 +81,12 @@ export class EditSchemaTransformationComponent implements OnInit {
     editTimestampDomainProperty(checked: boolean) {
         if (checked) {
             this.isTimestampProperty = true;
-            this.cachedProperty.domainProperties = [SemanticType.TIMESTAMP];
+            this.cachedProperty.semanticType = SemanticType.TIMESTAMP;
             this.cachedProperty.propertyScope = 'HEADER_PROPERTY';
-            this.cachedProperty.runtimeType = DataType.LONG;
+            (this.cachedProperty as EventPropertyPrimitive).runtimeType =
+                DataType.LONG;
         } else {
-            this.cachedProperty.domainProperties = [];
+            this.cachedProperty.semanticType = undefined;
             this.cachedProperty.propertyScope = 'MEASUREMENT_PROPERTY';
             this.isTimestampProperty = false;
         }
diff --git a/ui/src/app/connect/dialog/edit-event-property/edit-event-property.component.ts b/ui/src/app/connect/dialog/edit-event-property/edit-event-property.component.ts
index f5b527b7e1..0cff8aefd4 100644
--- a/ui/src/app/connect/dialog/edit-event-property/edit-event-property.component.ts
+++ b/ui/src/app/connect/dialog/edit-event-property/edit-event-property.component.ts
@@ -149,9 +149,7 @@ export class EditEventPropertyComponent implements OnInit {
         this.property.description = this.cachedProperty.description;
         this.property.elementId = this.cachedProperty.elementId;
 
-        // remove undefined from domain properties array
-        this.property.domainProperties =
-            this.cachedProperty.domainProperties.filter(n => n);
+        this.property.semanticType = this.cachedProperty.semanticType;
         this.property.runtimeName = this.cachedProperty.runtimeName;
         this.property.propertyScope = this.cachedProperty.propertyScope;
 
diff --git a/ui/src/app/connect/filter/timestamp.pipe.ts b/ui/src/app/connect/filter/timestamp.pipe.ts
index d3bd4b5c43..e863268f70 100644
--- a/ui/src/app/connect/filter/timestamp.pipe.ts
+++ b/ui/src/app/connect/filter/timestamp.pipe.ts
@@ -30,8 +30,6 @@ export class TimestampPipe implements PipeTransform {
     constructor() {}
 
     transform(items: EventPropertyUnion[]): EventPropertyUnion[] {
-        return items.filter(item =>
-            item.domainProperties.some(dp => dp === SemanticType.TIMESTAMP),
-        );
+        return items.filter(item => SemanticType.isTimestamp(item));
     }
 }
diff --git a/ui/src/app/connect/services/transformation-rule.service.ts b/ui/src/app/connect/services/transformation-rule.service.ts
index 2d04eb8876..b79883961a 100644
--- a/ui/src/app/connect/services/transformation-rule.service.ts
+++ b/ui/src/app/connect/services/transformation-rule.service.ts
@@ -89,9 +89,7 @@ export class TransformationRuleService {
                 rule.label = ep.label;
                 rule.description = ep.description;
                 rule.propertyScope = ep.propertyScope as PropertyScope;
-                if (ep.domainProperties.length > 0) {
-                    rule.semanticType = ep.domainProperties[0];
-                }
+                rule.semanticType = ep.semanticType;
                 rule.measurementUnit = ep.measurementUnit;
                 rule.staticValue =
                     this.staticValueTransformService.getStaticValue(
@@ -569,9 +567,7 @@ export class TransformationRuleService {
     }
 
     isTimestampProperty(property: EventPropertyPrimitive) {
-        return property.domainProperties.some(
-            dp => dp === SemanticType.TIMESTAMP,
-        );
+        return SemanticType.isTimestamp(property);
     }
 
     private getDatatypeTransformRules(
diff --git a/ui/src/app/core-ui/static-properties/static-property.component.html b/ui/src/app/core-ui/static-properties/static-property.component.html
index e416735c84..3f43c9bd03 100644
--- a/ui/src/app/core-ui/static-properties/static-property.component.html
+++ b/ui/src/app/core-ui/static-properties/static-property.component.html
@@ -94,6 +94,7 @@
                 [parentForm]="parentForm"
                 [completedStaticProperty]="completedStaticProperty"
                 [adapterId]="adapterId"
+                (updateEmitter)="emitUpdate($event)"
             >
             </sp-app-static-runtime-resolvable-any-input>
 
diff --git a/ui/src/app/core-ui/static-properties/static-runtime-resolvable-any-input/static-runtime-resolvable-any-input.component.html b/ui/src/app/core-ui/static-properties/static-runtime-resolvable-any-input/static-runtime-resolvable-any-input.component.html
index 4690c0f00c..ac1c4f7e54 100644
--- a/ui/src/app/core-ui/static-properties/static-runtime-resolvable-any-input/static-runtime-resolvable-any-input.component.html
+++ b/ui/src/app/core-ui/static-properties/static-runtime-resolvable-any-input/static-runtime-resolvable-any-input.component.html
@@ -17,48 +17,65 @@
   -->
 
 <div id="formWrapper" fxFlex="100" fxLayout="column">
-    <div>
+    <div fxLayout="row" class="mb-10">
+        <button
+            mat-button
+            mat-raised-button
+            color="accent"
+            class="small-button"
+            (click)="selectAll(true)"
+            [disabled]="!showOptions"
+        >
+            <span>Select all</span>
+        </button>
+        <button
+            mat-button
+            mat-raised-button
+            class="mat-basic small-button"
+            (click)="selectAll(false)"
+            [disabled]="!showOptions"
+        >
+            <span>Select none</span>
+        </button>
         <button
             mat-button
             mat-raised-button
             color="accent"
             class="small-button"
             (click)="loadOptionsFromRestApi()"
-            style="margin-right: 10px; margin-left: 10px"
             [disabled]="!showOptions"
         >
             <span>Reload</span>
         </button>
+        <mat-spinner
+            *ngIf="loading"
+            color="accent"
+            [mode]="'indeterminate'"
+            [diameter]="15"
+        ></mat-spinner>
     </div>
-    <div
-        *ngIf="!staticProperty.horizontalRendering"
-        fxLayout="column"
-        style="margin-top: 10px"
-    >
+    <div *ngIf="!staticProperty.horizontalRendering" fxLayout="column">
         <mat-checkbox
             style="padding-left: 10px"
             color="accent"
             *ngFor="let option of staticProperty.options"
             [(ngModel)]="option.selected"
+            (ngModelChange)="checkEmitUpdate()"
         >
             {{ option.name }}
         </mat-checkbox>
     </div>
-    <div fxLayout="column" *ngIf="!showOptions && !loading" class="mt-10">
+    <div fxLayout="column" *ngIf="!showOptions && !loading" class="mb-10">
         <span>(waiting for input)</span>
     </div>
-    <div fxLayout="column" *ngIf="loading">
-        <mat-spinner
-            color="accent"
-            [mode]="'indeterminate'"
-            [diameter]="20"
-        ></mat-spinner>
-    </div>
 
-    <div *ngIf="staticProperty.horizontalRendering">
+    <div *ngIf="staticProperty.horizontalRendering && showOptions">
         <mat-form-field style="width: 100%" color="accent">
-            <mat-label>{{ staticProperty.label }}</mat-label>
-            <mat-select multiple [(ngModel)]="option.selected">
+            <mat-select
+                multiple
+                [(ngModel)]="selectedOptions"
+                (selectionChange)="onSelectionChange()"
+            >
                 <mat-option
                     *ngFor="let option of staticProperty.options"
                     [value]="option"
@@ -66,7 +83,6 @@
                     {{ option.name }}
                 </mat-option>
             </mat-select>
-            <mat-hint>{{ staticProperty.description }}</mat-hint>
         </mat-form-field>
     </div>
 </div>
diff --git a/ui/src/app/core-ui/static-properties/static-runtime-resolvable-any-input/static-runtime-resolvable-any-input.component.ts b/ui/src/app/core-ui/static-properties/static-runtime-resolvable-any-input/static-runtime-resolvable-any-input.component.ts
index 2fb2ea4da5..6d84538535 100644
--- a/ui/src/app/core-ui/static-properties/static-runtime-resolvable-any-input/static-runtime-resolvable-any-input.component.ts
+++ b/ui/src/app/core-ui/static-properties/static-runtime-resolvable-any-input/static-runtime-resolvable-any-input.component.ts
@@ -18,11 +18,13 @@
 
 import { Component, OnInit } from '@angular/core';
 import {
+    Option,
     RuntimeResolvableAnyStaticProperty,
     StaticPropertyUnion,
 } from '@streampipes/platform-services';
 import { RuntimeResolvableService } from '../static-runtime-resolvable-input/runtime-resolvable.service';
 import { BaseRuntimeResolvableSelectionInput } from '../static-runtime-resolvable-input/base-runtime-resolvable-selection-input';
+import { MatSelectChange } from '@angular/material/select';
 
 @Component({
     selector: 'sp-app-static-runtime-resolvable-any-input',
@@ -33,25 +35,40 @@ export class StaticRuntimeResolvableAnyInputComponent
     extends BaseRuntimeResolvableSelectionInput<RuntimeResolvableAnyStaticProperty>
     implements OnInit
 {
+    selectedOptions: Option[] = [];
+
     constructor(runtimeResolvableService: RuntimeResolvableService) {
         super(runtimeResolvableService);
     }
 
     ngOnInit() {
         super.onInit();
+        this.selectedOptions = this.staticProperty.options.filter(
+            o => o.selected,
+        );
+    }
+
+    selectAll(select: boolean): void {
+        this.staticProperty.options.forEach(o => (o.selected = select));
+        this.selectedOptions = select ? this.staticProperty.options : [];
+        this.emitUpdate(true);
+    }
+
+    onSelectionChange(): void {
+        this.staticProperty.options.forEach(option => {
+            option.selected = this.selectedOptions.includes(option);
+        });
     }
 
-    select(id) {
-        for (const option of this.staticProperty.options) {
-            option.selected = false;
-        }
-        this.staticProperty.options.find(
-            option => option.elementId === id,
-        ).selected = true;
+    checkEmitUpdate(): void {
+        this.emitUpdate(true);
     }
 
     afterOptionsLoaded(staticProperty: RuntimeResolvableAnyStaticProperty) {
         this.staticProperty.options = staticProperty.options;
+        this.selectedOptions = this.staticProperty.options.filter(
+            o => o.selected,
+        );
     }
 
     parse(
diff --git a/ui/src/app/core-ui/static-properties/static-runtime-resolvable-tree-input/static-runtime-resolvable-tree-input.component.ts b/ui/src/app/core-ui/static-properties/static-runtime-resolvable-tree-input/static-runtime-resolvable-tree-input.component.ts
index 8d0ff9d3b2..7c306ce446 100644
--- a/ui/src/app/core-ui/static-properties/static-runtime-resolvable-tree-input/static-runtime-resolvable-tree-input.component.ts
+++ b/ui/src/app/core-ui/static-properties/static-runtime-resolvable-tree-input/static-runtime-resolvable-tree-input.component.ts
@@ -58,7 +58,17 @@ export class StaticRuntimeResolvableTreeInputComponent
     }
 
     ngOnInit(): void {
-        this.resetStaticPropertyState();
+        // if a node is selected it is assumed the adapter was opened in edit mode
+        // when that is the case, the browse tree should be reloaded
+        // if the adapter is created, the reload should only be triggered if all previous configurations are set correctly
+        if (
+            this.staticProperty.selectedNodesInternalNames &&
+            this.staticProperty.selectedNodesInternalNames.length > 0
+        ) {
+            this.resetStaticPropertyStateAndReload();
+        } else {
+            this.resetStaticPropertyState();
+        }
 
         if (
             this.staticProperty.nodes.length === 0 &&
diff --git a/ui/src/app/core-ui/static-properties/static-slide-toggle/static-slide-toggle.component.html b/ui/src/app/core-ui/static-properties/static-slide-toggle/static-slide-toggle.component.html
index 0863899fa6..e3a4e5c69c 100644
--- a/ui/src/app/core-ui/static-properties/static-slide-toggle/static-slide-toggle.component.html
+++ b/ui/src/app/core-ui/static-properties/static-slide-toggle/static-slide-toggle.component.html
@@ -22,7 +22,6 @@
             fxFlex
             formControlName="{{ fieldName }}"
             color="accent"
-            required
             [attr.data-cy]="fieldName"
         >
             {{ staticProperty.description }}
diff --git a/ui/src/app/core-ui/static-properties/static-slide-toggle/static-slide-toggle.component.ts b/ui/src/app/core-ui/static-properties/static-slide-toggle/static-slide-toggle.component.ts
index 64e17a6005..e74274ae7f 100644
--- a/ui/src/app/core-ui/static-properties/static-slide-toggle/static-slide-toggle.component.ts
+++ b/ui/src/app/core-ui/static-properties/static-slide-toggle/static-slide-toggle.component.ts
@@ -33,6 +33,7 @@ export class StaticSlideToggleComponent
     ngOnInit(): void {
         this.addValidator(this.staticProperty.selected, Validators.required);
         this.enableValidators();
+        this.emitUpdate();
     }
 
     emitUpdate() {
diff --git a/ui/src/app/dashboard/components/widgets/table/table-widget.component.ts b/ui/src/app/dashboard/components/widgets/table/table-widget.component.ts
index 54693b732e..768ee61ebb 100644
--- a/ui/src/app/dashboard/components/widgets/table/table-widget.component.ts
+++ b/ui/src/app/dashboard/components/widgets/table/table-widget.component.ts
@@ -57,7 +57,7 @@ export class TableWidgetComponent
 
         this.widgetDataConfig.eventSchema.eventProperties.forEach(
             (key, index) => {
-                this.semanticTypes[key.runtimeName] = key.domainProperties[0];
+                this.semanticTypes[key.runtimeName] = key.semanticType;
             },
         );
         this.semanticTypes[BaseStreamPipesWidget.TIMESTAMP_KEY] =
diff --git a/ui/src/app/dashboard/sdk/ep-requirements.ts b/ui/src/app/dashboard/sdk/ep-requirements.ts
index 3196a11ced..58b830c43f 100644
--- a/ui/src/app/dashboard/sdk/ep-requirements.ts
+++ b/ui/src/app/dashboard/sdk/ep-requirements.ts
@@ -104,9 +104,9 @@ export class EpRequirements {
         return listEp;
     }
 
-    static domainPropertyReq(domainProperty: string): EventPropertyPrimitive {
+    static domainPropertyReq(semanticType: string): EventPropertyPrimitive {
         const eventProperty = EpRequirements.ep();
-        eventProperty.domainProperties = [domainProperty];
+        eventProperty.semanticType = semanticType;
         return eventProperty;
     }
 
diff --git a/ui/src/app/dashboard/sdk/matching/domain-property-match.ts b/ui/src/app/dashboard/sdk/matching/domain-property-match.ts
index 3c319f5866..92c9c1f5e7 100644
--- a/ui/src/app/dashboard/sdk/matching/domain-property-match.ts
+++ b/ui/src/app/dashboard/sdk/matching/domain-property-match.ts
@@ -17,22 +17,17 @@
  */
 
 export class DomainPropertyMatch {
-    match(
-        domainPropertyRequirements: string[],
-        domainPropertyOffers: string[],
-    ) {
+    match(domainPropertyRequirement: string, domainPropertyOffer: string) {
         if (
-            domainPropertyRequirements === undefined ||
-            domainPropertyRequirements.length === 0
+            domainPropertyRequirement === undefined ||
+            domainPropertyRequirement === ''
         ) {
             return true;
         } else {
-            if (!domainPropertyOffers) {
+            if (!domainPropertyOffer) {
                 return false;
             } else {
-                return (
-                    domainPropertyRequirements[0] === domainPropertyOffers[0]
-                );
+                return domainPropertyRequirement === domainPropertyOffer;
             }
         }
     }
diff --git a/ui/src/app/dashboard/sdk/matching/primitive-property-match.ts b/ui/src/app/dashboard/sdk/matching/primitive-property-match.ts
index dea6f256a3..8ecb8ebe81 100644
--- a/ui/src/app/dashboard/sdk/matching/primitive-property-match.ts
+++ b/ui/src/app/dashboard/sdk/matching/primitive-property-match.ts
@@ -29,8 +29,8 @@ export class PrimitivePropertyMatch {
                     offer.runtimeType,
                 ) &&
                 new DomainPropertyMatch().match(
-                    requirement.domainProperties,
-                    offer.domainProperties,
+                    requirement.semanticType,
+                    offer.semanticType,
                 )
             );
         } else {
diff --git a/ui/src/app/data-explorer/components/time-selector/time-selector-menu/custom-time-range-selection/custom-time-range-selection.component.html b/ui/src/app/data-explorer/components/time-selector/time-selector-menu/custom-time-range-selection/custom-time-range-selection.component.html
index 9e277f0ca6..1564d9b5dc 100644
--- a/ui/src/app/data-explorer/components/time-selector/time-selector-menu/custom-time-range-selection/custom-time-range-selection.component.html
+++ b/ui/src/app/data-explorer/components/time-selector/time-selector-menu/custom-time-range-selection/custom-time-range-selection.component.html
@@ -74,6 +74,7 @@
         </div>
     </div>
     <div fxLayout="row" fxLayoutAlign="end center" class="mt-10">
+        <ng-content> </ng-content>
         <button
             mat-raised-button
             color="accent"
diff --git a/ui/src/app/data-explorer/components/time-selector/time-selector-menu/time-selector-menu.component.html b/ui/src/app/data-explorer/components/time-selector/time-selector-menu/time-selector-menu.component.html
index 70ded63676..e53550aa43 100644
--- a/ui/src/app/data-explorer/components/time-selector/time-selector-menu/time-selector-menu.component.html
+++ b/ui/src/app/data-explorer/components/time-selector/time-selector-menu/time-selector-menu.component.html
@@ -46,6 +46,7 @@
                     (timeSettingsEmitter)="timeSettingsEmitter.emit($event)"
                     class="w-100"
                 >
+                    <ng-content> </ng-content>
                 </sp-custom-time-range-selection>
             </div>
         </div>
diff --git a/ui/src/app/data-explorer/components/widget/data-explorer-dashboard-widget.component.html b/ui/src/app/data-explorer/components/widget/data-explorer-dashboard-widget.component.html
index fa9617a0ed..ea476a9846 100644
--- a/ui/src/app/data-explorer/components/widget/data-explorer-dashboard-widget.component.html
+++ b/ui/src/app/data-explorer/components/widget/data-explorer-dashboard-widget.component.html
@@ -111,6 +111,34 @@
                 >
                     <mat-icon>get_app</mat-icon>
                 </button>
+                <button
+                    mat-icon-button
+                    [matMenuTriggerFor]="optMenu"
+                    *ngIf="!globalTimeEnabled"
+                    aria-label="Options"
+                    data-cy="options-data-explorer"
+                    #menuTrigger="matMenuTrigger"
+                >
+                    <mat-icon
+                        [color]="timeSettingsModified ? 'primary' : 'default'"
+                        >alarm_clock</mat-icon
+                    >
+                </button>
+                <mat-menu #optMenu="matMenu" class="large-menu">
+                    <sp-time-selector-menu
+                        [timeSettings]="clonedTimeSettings"
+                        (timeSettingsEmitter)="modifyWidgetTimeSettings($event)"
+                        class="w-100"
+                    >
+                        <button
+                            mat-raised-button
+                            class="mat-basic"
+                            (click)="resetWidgetTimeSettings()"
+                        >
+                            Reset
+                        </button>
+                    </sp-time-selector-menu>
+                </mat-menu>
                 <button
                     mat-icon-button
                     (click)="removeWidget()"
diff --git a/ui/src/app/data-explorer/components/widget/data-explorer-dashboard-widget.component.ts b/ui/src/app/data-explorer/components/widget/data-explorer-dashboard-widget.component.ts
index 9e3e962de2..21e5170c0e 100644
--- a/ui/src/app/data-explorer/components/widget/data-explorer-dashboard-widget.component.ts
+++ b/ui/src/app/data-explorer/components/widget/data-explorer-dashboard-widget.component.ts
@@ -22,9 +22,11 @@ import {
     ComponentRef,
     EventEmitter,
     Input,
+    OnChanges,
     OnDestroy,
     OnInit,
     Output,
+    SimpleChanges,
     ViewChild,
 } from '@angular/core';
 import { GridsterItemComponent } from 'angular-gridster2';
@@ -45,13 +47,18 @@ import { UserPrivilege } from '../../../_enums/user-privilege.enum';
 import { CurrentUserService } from '@streampipes/shared-ui';
 import { BaseWidgetData } from '../../models/dataview-dashboard.model';
 import { DataExplorerDashboardService } from '../../services/data-explorer-dashboard.service';
+import { TimeSelectionService } from '../../services/time-selection.service';
+import { MatMenuTrigger } from '@angular/material/menu';
 
 @Component({
     selector: 'sp-data-explorer-dashboard-widget',
     templateUrl: './data-explorer-dashboard-widget.component.html',
     styleUrls: ['./data-explorer-dashboard-widget.component.scss'],
 })
-export class DataExplorerDashboardWidgetComponent implements OnInit, OnDestroy {
+export class DataExplorerDashboardWidgetComponent
+    implements OnInit, OnDestroy, OnChanges
+{
+    @ViewChild('menuTrigger') menu: MatMenuTrigger;
     @Input()
     dashboardItem: DashboardItem;
 
@@ -97,6 +104,9 @@ export class DataExplorerDashboardWidgetComponent implements OnInit, OnDestroy {
     timerActive = false;
     loadingTime = 0;
 
+    clonedTimeSettings: TimeSettings;
+    timeSettingsModified: boolean = false;
+
     hasDataExplorerWritePrivileges = false;
 
     authSubscription: Subscription;
@@ -116,8 +126,16 @@ export class DataExplorerDashboardWidgetComponent implements OnInit, OnDestroy {
         private widgetTypeService: WidgetTypeService,
         private authService: AuthService,
         private currentUserService: CurrentUserService,
+        private timeSelectionService: TimeSelectionService,
     ) {}
 
+    ngOnChanges(changes: SimpleChanges): void {
+        if (changes.widgetIndex && this.componentRef?.instance) {
+            this.componentRef.instance.widgetIndex =
+                changes.widgetIndex.currentValue;
+        }
+    }
+
     ngOnInit(): void {
         this.authSubscription = this.currentUserService.user$.subscribe(
             user => {
@@ -139,6 +157,14 @@ export class DataExplorerDashboardWidgetComponent implements OnInit, OnDestroy {
                 },
             );
         this.chooseWidget(this.configuredWidget.widgetType);
+        this.clonedTimeSettings = {
+            startTime: this.timeSettings.startTime,
+            endTime: this.timeSettings.endTime,
+            timeSelectionId: this.timeSettings.timeSelectionId,
+        };
+        if (this.dashboardItem.timeSettings !== undefined) {
+            this.timeSettingsModified = true;
+        }
     }
 
     ngOnDestroy() {
@@ -176,6 +202,7 @@ export class DataExplorerDashboardWidgetComponent implements OnInit, OnDestroy {
         this.componentRef.instance.dataExplorerWidget = this.configuredWidget;
         this.componentRef.instance.previewMode = this.previewMode;
         this.componentRef.instance.gridMode = this.gridMode;
+        this.componentRef.instance.widgetIndex = this.widgetIndex;
         const removeSub =
             this.componentRef.instance.removeWidgetCallback.subscribe(ev =>
                 this.removeWidget(),
@@ -196,9 +223,13 @@ export class DataExplorerDashboardWidgetComponent implements OnInit, OnDestroy {
     }
 
     getTimeSettings(): TimeSettings {
-        return this.globalTimeEnabled
-            ? this.timeSettings
-            : (this.configuredWidget.timeSettings as TimeSettings);
+        if (this.globalTimeEnabled) {
+            return this.timeSettings;
+        } else if (this.dashboardItem.timeSettings !== undefined) {
+            return this.dashboardItem.timeSettings as TimeSettings;
+        } else {
+            return this.configuredWidget.timeSettings as TimeSettings;
+        }
     }
 
     removeWidget() {
@@ -233,4 +264,26 @@ export class DataExplorerDashboardWidgetComponent implements OnInit, OnDestroy {
             this.configuredWidget,
         );
     }
+
+    modifyWidgetTimeSettings(timeSettings: TimeSettings): void {
+        this.dashboardItem.timeSettings = timeSettings;
+        this.timeSelectionService.notify(timeSettings, this.widgetIndex);
+        this.menu.closeMenu();
+        this.timeSettingsModified = true;
+    }
+
+    resetWidgetTimeSettings(): void {
+        this.dashboardItem.timeSettings = undefined;
+        this.clonedTimeSettings = {
+            startTime: this.timeSettings.startTime,
+            endTime: this.timeSettings.endTime,
+            timeSelectionId: this.timeSettings.timeSelectionId,
+        };
+        this.timeSelectionService.notify(
+            this.getTimeSettings(),
+            this.widgetIndex,
+        );
+        this.menu.closeMenu();
+        this.timeSettingsModified = false;
+    }
 }
diff --git a/ui/src/app/data-explorer/components/widgets/base/base-data-explorer-widget.directive.ts b/ui/src/app/data-explorer/components/widgets/base/base-data-explorer-widget.directive.ts
index b8e86ffdb9..5df627e9e7 100644
--- a/ui/src/app/data-explorer/components/widgets/base/base-data-explorer-widget.directive.ts
+++ b/ui/src/app/data-explorer/components/widgets/base/base-data-explorer-widget.directive.ts
@@ -83,6 +83,9 @@ export abstract class BaseDataExplorerWidgetDirective<
     @Input() dataViewDashboardItem: DashboardItem;
     @Input() dataExplorerWidget: T;
 
+    @Input()
+    widgetIndex: number;
+
     @HostBinding('class') className = 'h-100';
 
     public selectedProperties: string[];
@@ -193,16 +196,21 @@ export abstract class BaseDataExplorerWidgetDirective<
         }
         this.timeSelectionSub =
             this.timeSelectionService.timeSelectionChangeSubject.subscribe(
-                ts => {
-                    if (ts) {
-                        this.timeSettings = ts;
-                    } else {
-                        this.timeSelectionService.updateTimeSettings(
-                            this.timeSettings,
-                            new Date(),
-                        );
+                widgetTimeSettings => {
+                    if (
+                        widgetTimeSettings.widgetIndex === undefined ||
+                        widgetTimeSettings.widgetIndex === this.widgetIndex
+                    ) {
+                        if (widgetTimeSettings.timeSettings) {
+                            this.timeSettings = widgetTimeSettings.timeSettings;
+                        } else {
+                            this.timeSelectionService.updateTimeSettings(
+                                this.timeSettings,
+                                new Date(),
+                            );
+                        }
+                        this.updateData();
                     }
-                    this.updateData();
                 },
             );
         this.updateData();
diff --git a/ui/src/app/data-explorer/components/widgets/pie/config/pie-chart-widget-config.component.html b/ui/src/app/data-explorer/components/widgets/pie/config/pie-chart-widget-config.component.html
index fd1abc5775..b6b4b44d2e 100644
--- a/ui/src/app/data-explorer/components/widgets/pie/config/pie-chart-widget-config.component.html
+++ b/ui/src/app/data-explorer/components/widgets/pie/config/pie-chart-widget-config.component.html
@@ -38,33 +38,55 @@
                 ?.fieldCharacteristics.numeric
         "
     >
-        <div
-            fxFlex="100"
-            fxLayout="row"
-            fxLayoutAlign="start center"
-            fxLayoutGap="10px"
-        >
-            <small>Rounding</small>
-            <mat-form-field
-                appearance="outline"
-                class="marginColorField"
-                color="accent"
-                fxFlex
+        <div fxLayout="column" fxLayoutGap="10px">
+            <div
+                fxFlex="100"
+                fxLayout="row"
+                fxLayoutAlign="start center"
+                fxLayoutGap="10px"
             >
-                <mat-select
-                    [(value)]="
-                        currentlyConfiguredWidget.visualizationConfig
-                            .roundingValue
-                    "
-                    (selectionChange)="updateRoundingValue($event.value)"
+                <small>Rounding</small>
+                <mat-form-field
+                    appearance="outline"
+                    class="marginColorField"
+                    color="accent"
+                    fxFlex
                 >
-                    <mat-option [value]="100">100</mat-option>
-                    <mat-option [value]="10">10</mat-option>
-                    <mat-option [value]="1">1</mat-option>
-                    <mat-option [value]="0.1">0.1</mat-option>
-                    <mat-option [value]="0.01">0.01</mat-option>
-                </mat-select>
-            </mat-form-field>
+                    <mat-select
+                        [(value)]="
+                            currentlyConfiguredWidget.visualizationConfig
+                                .roundingValue
+                        "
+                        (selectionChange)="updateRoundingValue($event.value)"
+                    >
+                        <mat-option [value]="100">100</mat-option>
+                        <mat-option [value]="10">10</mat-option>
+                        <mat-option [value]="1">1</mat-option>
+                        <mat-option [value]="0.1">0.1</mat-option>
+                        <mat-option [value]="0.01">0.01</mat-option>
+                    </mat-select>
+                </mat-form-field>
+            </div>
+            <div
+                fxFlex="100"
+                fxLayout="row"
+                fxLayoutAlign="start center"
+                fxLayoutGap="10px"
+            >
+                <small>Inner Radius</small>
+                <mat-slider min="0" max="80" step="1" fxFlex="65">
+                    <input
+                        matSliderThumb
+                        [ngModel]="
+                            currentlyConfiguredWidget.visualizationConfig
+                                .selectedRadius
+                        "
+                        (ngModelChange)="updateInnerRadius($event)"
+                        #slider
+                    />
+                </mat-slider>
+                <small>{{ slider.value }}% </small>
+            </div>
         </div>
     </sp-configuration-box>
 </sp-visualization-config-outer>
diff --git a/ui/src/app/data-explorer/components/widgets/pie/config/pie-chart-widget-config.component.ts b/ui/src/app/data-explorer/components/widgets/pie/config/pie-chart-widget-config.component.ts
index 39d2909449..e93dd8541d 100644
--- a/ui/src/app/data-explorer/components/widgets/pie/config/pie-chart-widget-config.component.ts
+++ b/ui/src/app/data-explorer/components/widgets/pie/config/pie-chart-widget-config.component.ts
@@ -45,6 +45,7 @@ export class SpPieChartWidgetConfigComponent extends BaseWidgetConfig<
             () => this.fieldProvider.allFields[0],
         );
         config.roundingValue ??= 0.1;
+        config.selectedRadius ??= 0;
     }
 
     updateRoundingValue(selectedType: number) {
@@ -53,6 +54,12 @@ export class SpPieChartWidgetConfigComponent extends BaseWidgetConfig<
         this.triggerViewRefresh();
     }
 
+    updateInnerRadius(selectedRadius: number) {
+        this.currentlyConfiguredWidget.visualizationConfig.selectedRadius =
+            selectedRadius;
+        this.triggerViewRefresh();
+    }
+
     protected requiredFieldsForChartPresent(): boolean {
         return this.fieldProvider.allFields.length > 0;
     }
diff --git a/ui/src/app/data-explorer/components/widgets/pie/model/pie-chart-widget.model.ts b/ui/src/app/data-explorer/components/widgets/pie/model/pie-chart-widget.model.ts
index 5ea5d22fdc..a846ad00b8 100644
--- a/ui/src/app/data-explorer/components/widgets/pie/model/pie-chart-widget.model.ts
+++ b/ui/src/app/data-explorer/components/widgets/pie/model/pie-chart-widget.model.ts
@@ -26,6 +26,7 @@ import { DataExplorerVisConfig } from '../../../../models/dataview-dashboard.mod
 export interface PieChartVisConfig extends DataExplorerVisConfig {
     selectedProperty: DataExplorerField;
     roundingValue: number;
+    selectedRadius: number;
 }
 
 export interface PieChartWidgetModel extends DataExplorerWidgetModel {
diff --git a/ui/src/app/data-explorer/components/widgets/pie/pie-renderer.service.ts b/ui/src/app/data-explorer/components/widgets/pie/pie-renderer.service.ts
index 84346d9218..be48f98ae8 100644
--- a/ui/src/app/data-explorer/components/widgets/pie/pie-renderer.service.ts
+++ b/ui/src/app/data-explorer/components/widgets/pie/pie-renderer.service.ts
@@ -64,6 +64,7 @@ export class SpPieRendererService extends SpBaseSingleFieldEchartsRenderer<
         datasetIndex: number,
         _widgetConfig: PieChartWidgetModel,
     ): PieSeriesOption {
+        const innerRadius = _widgetConfig.visualizationConfig.selectedRadius;
         return {
             name,
             type: 'pie',
@@ -80,6 +81,7 @@ export class SpPieRendererService extends SpBaseSingleFieldEchartsRenderer<
                 },
             },
             encode: { itemName: 'name', value: 'value' },
+            radius: [innerRadius + '%', '90%'],
         };
     }
 
diff --git a/ui/src/app/data-explorer/dialogs/edit-dashboard/data-explorer-edit-dashboard-dialog.component.html b/ui/src/app/data-explorer/dialogs/edit-dashboard/data-explorer-edit-dashboard-dialog.component.html
index de73ccaeff..98b4312145 100644
--- a/ui/src/app/data-explorer/dialogs/edit-dashboard/data-explorer-edit-dashboard-dialog.component.html
+++ b/ui/src/app/data-explorer/dialogs/edit-dashboard/data-explorer-edit-dashboard-dialog.component.html
@@ -67,7 +67,8 @@
                         [(ngModel)]="
                             dashboard.dashboardGeneralSettings.globalTimeEnabled
                         "
-                        >Use global time instead of widget time settings
+                        >Use global time settings instead of widget time
+                        settings
                     </mat-checkbox>
                 </div>
                 <!--<mat-checkbox [(ngModel)]="dashboard.displayHeader">Show name and description in dashboard</mat-checkbox>-->
diff --git a/ui/src/app/data-explorer/models/dataview-dashboard.model.ts b/ui/src/app/data-explorer/models/dataview-dashboard.model.ts
index 670c73a29d..d3597f69db 100644
--- a/ui/src/app/data-explorer/models/dataview-dashboard.model.ts
+++ b/ui/src/app/data-explorer/models/dataview-dashboard.model.ts
@@ -54,6 +54,7 @@ export interface BaseWidgetData<T extends DataExplorerWidgetModel> {
     dataExplorerWidget: T;
     previewMode: boolean;
     gridMode: boolean;
+    widgetIndex?: number;
 
     cleanupSubscriptions(): void;
 }
diff --git a/ui/src/app/data-explorer/services/data-explorer-field-provider-service.ts b/ui/src/app/data-explorer/services/data-explorer-field-provider-service.ts
index 40a9e91309..166ba89413 100644
--- a/ui/src/app/data-explorer/services/data-explorer-field-provider-service.ts
+++ b/ui/src/app/data-explorer/services/data-explorer-field-provider-service.ts
@@ -113,7 +113,7 @@ export class DataExplorerFieldProviderService {
                 dimension: this.isDimensionProperty(property),
                 numeric: this.isNumber(property) || aggregation === 'COUNT',
                 binary: this.isBoolean(property),
-                semanticTypes: property.domainProperties,
+                semanticTypes: [property.semanticType],
             },
         };
         provider.allFields.push(field);
@@ -156,7 +156,7 @@ export class DataExplorerFieldProviderService {
     }
 
     public isTimestamp(p: EventProperty) {
-        return p.domainProperties.some(dp => dp === SemanticType.TIMESTAMP);
+        return SemanticType.isTimestamp(p);
     }
 
     public getAddedFields(
diff --git a/ui/src/app/data-explorer/services/time-selection.service.ts b/ui/src/app/data-explorer/services/time-selection.service.ts
index 11a9515cfc..5c55e7756a 100644
--- a/ui/src/app/data-explorer/services/time-selection.service.ts
+++ b/ui/src/app/data-explorer/services/time-selection.service.ts
@@ -23,6 +23,7 @@ import {
     QuickTimeSelection,
     TimeSelectionId,
     TimeSettings,
+    WidgetTimeSettings,
 } from '@streampipes/platform-services';
 import {
     startOfDay,
@@ -178,10 +179,11 @@ export class TimeSelectionService {
         }
     }
 
-    public timeSelectionChangeSubject: Subject<TimeSettings | undefined> =
-        new Subject<TimeSettings | undefined>();
+    public timeSelectionChangeSubject: Subject<WidgetTimeSettings | undefined> =
+        new Subject<WidgetTimeSettings | undefined>();
 
-    public notify(timeSettings?: TimeSettings): void {
-        this.timeSelectionChangeSubject.next(timeSettings);
+    public notify(timeSettings?: TimeSettings, widgetIndex?: number): void {
+        const widgetTimeSettings = { timeSettings, widgetIndex };
+        this.timeSelectionChangeSubject.next(widgetTimeSettings);
     }
 }
diff --git a/ui/src/app/editor/components/output-strategy/user-defined-output/user-defined-output.component.html b/ui/src/app/editor/components/output-strategy/user-defined-output/user-defined-output.component.html
index 9c6d61eb2a..1ebc5d00e6 100644
--- a/ui/src/app/editor/components/output-strategy/user-defined-output/user-defined-output.component.html
+++ b/ui/src/app/editor/components/output-strategy/user-defined-output/user-defined-output.component.html
@@ -75,7 +75,7 @@
             <mat-form-field fxFlex color="accent">
                 <mat-label>Semantic type</mat-label>
                 <input
-                    [(ngModel)]="ep.domainProperties[0]"
+                    [(ngModel)]="ep.semanticType"
                     [disabled]="restrictedEditMode"
                     data-cy="semantic-type"
                     fxFlex
diff --git a/ui/src/app/editor/components/output-strategy/user-defined-output/user-defined-output.component.ts b/ui/src/app/editor/components/output-strategy/user-defined-output/user-defined-output.component.ts
index 94576ade12..97170d9547 100644
--- a/ui/src/app/editor/components/output-strategy/user-defined-output/user-defined-output.component.ts
+++ b/ui/src/app/editor/components/output-strategy/user-defined-output/user-defined-output.component.ts
@@ -81,7 +81,7 @@ export class UserDefinedOutputStrategyComponent
         const ep = {} as EventPropertyPrimitive;
         ep['@class'] =
             'org.apache.streampipes.model.schema.EventPropertyPrimitive';
-        ep.domainProperties = [];
+        ep.semanticType = undefined;
         ep.elementId =
             'urn:streampipes.org:spi:eventpropertyprimitive:' +
             this.idGeneratorService.generatePrefixedId();


Test patch:
diff --git a/streampipes-client-python/tests/client/test_endpoint.py b/streampipes-client-python/tests/client/test_endpoint.py
index ccf1a3bee3..5b71d83531 100644
--- a/streampipes-client-python/tests/client/test_endpoint.py
+++ b/streampipes-client-python/tests/client/test_endpoint.py
@@ -53,7 +53,7 @@ class TestStreamPipesEndpoints(TestCase):
                             "label": "Density",
                             "description": "Denotes the current density of the fluid",
                             "runtimeName": "density",
-                            "domainProperties": ["http://schema.org/Number"],
+                            "semanticType": "http://schema.org/Number",
                             "propertyScope": "MEASUREMENT_PROPERTY",
                             "runtimeId": None,
                             "runtimeType": "http://www.w3.org/2001/XMLSchema#float",
@@ -66,7 +66,7 @@ class TestStreamPipesEndpoints(TestCase):
                             "label": "Temperature",
                             "description": "Denotes the current temperature in degrees celsius",
                             "runtimeName": "temperature",
-                            "domainProperties": ["http://schema.org/Number"],
+                            "semanticType": "http://schema.org/Number",
                             "propertyScope": "MEASUREMENT_PROPERTY",
                             "runtimeId": None,
                             "runtimeType": "http://www.w3.org/2001/XMLSchema#float",
@@ -131,7 +131,7 @@ class TestStreamPipesEndpoints(TestCase):
                             "label": "Density",
                             "description": "Denotes the current density of the fluid",
                             "runtimeName": "density",
-                            "domainProperties": ["http://schema.org/Number"],
+                            "semanticType": "http://schema.org/Number",
                             "propertyScope": "MEASUREMENT_PROPERTY",
                             "runtimeId": None,
                             "runtimeType": "http://www.w3.org/2001/XMLSchema#float",
@@ -144,7 +144,7 @@ class TestStreamPipesEndpoints(TestCase):
                             "label": "Temperature",
                             "description": "Denotes the current temperature in degrees celsius",
                             "runtimeName": "temperature",
-                            "domainProperties": ["http://schema.org/Number"],
+                            "semanticType": "http://schema.org/Number",
                             "propertyScope": "MEASUREMENT_PROPERTY",
                             "runtimeId": None,
                             "runtimeType": "http://www.w3.org/2001/XMLSchema#float",
diff --git a/streampipes-connect-management/src/test/java/org/apache/streampipes/connect/management/management/compact/generator/AdapterSchemaGeneratorTest.java b/streampipes-connect-management/src/test/java/org/apache/streampipes/connect/management/management/compact/generator/AdapterSchemaGeneratorTest.java
index ef123ae80d..56d3203519 100644
--- a/streampipes-connect-management/src/test/java/org/apache/streampipes/connect/management/management/compact/generator/AdapterSchemaGeneratorTest.java
+++ b/streampipes-connect-management/src/test/java/org/apache/streampipes/connect/management/management/compact/generator/AdapterSchemaGeneratorTest.java
@@ -72,6 +72,6 @@ public class AdapterSchemaGeneratorTest {
     );
     assertEquals("description", properties.get(0).getDescription());
     assertEquals(PropertyScope.DIMENSION_PROPERTY.name(), properties.get(0).getPropertyScope());
-    assertEquals("semanticType", properties.get(0).getDomainProperties().get(0).toString());
+    assertEquals("semanticType", properties.get(0).getSemanticType());
   }
 }
diff --git a/streampipes-data-explorer-influx/src/test/java/org/apache/streampipes/dataexplorer/influx/PropertyDuplicateFilterTest.java b/streampipes-data-explorer-influx/src/test/java/org/apache/streampipes/dataexplorer/influx/PropertyDuplicateFilterTest.java
new file mode 100644
index 0000000000..0b9acb8a62
--- /dev/null
+++ b/streampipes-data-explorer-influx/src/test/java/org/apache/streampipes/dataexplorer/influx/PropertyDuplicateFilterTest.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.dataexplorer.influx;
+
+import org.apache.streampipes.model.runtime.field.PrimitiveField;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class PropertyDuplicateFilterTest {
+
+  @Test
+  public void testDuplicate() {
+    var filter = new PropertyDuplicateFilter(true);
+    var field = new PrimitiveField(null, null, 1);
+    var result = filter.shouldIgnoreField("test", field);
+
+    assertFalse(result);
+
+    field = new PrimitiveField(null, null, 2);
+    result = filter.shouldIgnoreField("test", field);
+    assertFalse(result);
+
+    field = new PrimitiveField(null, null, 2);
+    result = filter.shouldIgnoreField("test1", field);
+    assertFalse(result);
+
+    field = new PrimitiveField(null, null, 2);
+    result = filter.shouldIgnoreField("test", field);
+    assertTrue(result);
+  }
+
+  @Test
+  public void testDuplicateDeactivated() {
+    var filter = new PropertyDuplicateFilter(false);
+    var field = new PrimitiveField(null, null, 1);
+    var result = filter.shouldIgnoreField("test", field);
+
+    assertFalse(result);
+
+    field = new PrimitiveField(null, null, 1);
+    result = filter.shouldIgnoreField("test", field);
+    assertFalse(result);
+  }
+}
diff --git a/streampipes-data-explorer-iotdb/src/test/java/org/apache/streampipes/dataexplorer/iotdb/IotDbPropertyConverterTest.java b/streampipes-data-explorer-iotdb/src/test/java/org/apache/streampipes/dataexplorer/iotdb/IotDbPropertyConverterTest.java
index 5b7085784e..0c09c71977 100644
--- a/streampipes-data-explorer-iotdb/src/test/java/org/apache/streampipes/dataexplorer/iotdb/IotDbPropertyConverterTest.java
+++ b/streampipes-data-explorer-iotdb/src/test/java/org/apache/streampipes/dataexplorer/iotdb/IotDbPropertyConverterTest.java
@@ -18,12 +18,13 @@
 
 package org.apache.streampipes.dataexplorer.iotdb;
 
-import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
 import org.apache.streampipes.commons.exceptions.SpRuntimeException;
 import org.apache.streampipes.model.runtime.field.PrimitiveField;
 import org.apache.streampipes.model.schema.EventPropertyPrimitive;
 import org.apache.streampipes.vocabulary.SO;
 import org.apache.streampipes.vocabulary.XSD;
+
+import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -42,7 +43,7 @@ public class IotDbPropertyConverterTest {
   @Test
   public void convertPrimitivePropertyInteger() {
 
-    var property = new EventPropertyPrimitive(XSD.INTEGER.toString(), "test", null, null);
+    var property = new EventPropertyPrimitive(XSD.INTEGER.toString(), "test", null, "");
     var field = new PrimitiveField("test", "test", 5);
 
     var result = new IotDbPropertyConverter().convertPrimitiveProperty(property, field, "sanitizedTest");
@@ -55,7 +56,7 @@ public class IotDbPropertyConverterTest {
   @Test
   public void convertPrimitivePropertyString() {
 
-    var property = new EventPropertyPrimitive(XSD.STRING.toString(), "test", null, null);
+    var property = new EventPropertyPrimitive(XSD.STRING.toString(), "test", null, "");
     var field = new PrimitiveField("test", "test", "value");
 
     var result = new IotDbPropertyConverter().convertPrimitiveProperty(property, field, "sanitizedTest");
@@ -68,7 +69,7 @@ public class IotDbPropertyConverterTest {
   @Test
   public void convertPrimitivePropertyFloat() {
 
-    var property = new EventPropertyPrimitive(XSD.FLOAT.toString(), "test", null, null);
+    var property = new EventPropertyPrimitive(XSD.FLOAT.toString(), "test", null, "");
     var field = new PrimitiveField("test", "test", 0.5f);
 
     var result = new IotDbPropertyConverter().convertPrimitiveProperty(property, field, "sanitizedTest");
@@ -81,7 +82,7 @@ public class IotDbPropertyConverterTest {
   @Test
   public void convertPrimitivePropertyNumber() {
 
-    var property = new EventPropertyPrimitive(SO.NUMBER, "test", null, null);
+    var property = new EventPropertyPrimitive(SO.NUMBER, "test", null, "");
     var field = new PrimitiveField("test", "test", 5.24);
 
     var result = new IotDbPropertyConverter().convertPrimitiveProperty(property, field, "sanitizedTest");
@@ -94,7 +95,7 @@ public class IotDbPropertyConverterTest {
   @Test
   public void convertPrimitivePropertyUnknown() {
 
-    var property = new EventPropertyPrimitive(XSD.ANY_TYPE.toString(), "test", null, null);
+    var property = new EventPropertyPrimitive(XSD.ANY_TYPE.toString(), "test", null, "");
     var field = new PrimitiveField("test", "test", 5);
 
     assertThrows(SpRuntimeException.class, () -> new IotDbPropertyConverter().convertPrimitiveProperty(property, field, "sanitizedTest"));
diff --git a/streampipes-extensions/streampipes-sinks-internal-jvm/src/test/java/org/apache/streampipes/sinks/internal/jvm/datalake/migrations/DataLakeSinkMigrationV2Test.java b/streampipes-extensions/streampipes-sinks-internal-jvm/src/test/java/org/apache/streampipes/sinks/internal/jvm/datalake/migrations/DataLakeSinkMigrationV2Test.java
new file mode 100644
index 0000000000..3a3e2e272f
--- /dev/null
+++ b/streampipes-extensions/streampipes-sinks-internal-jvm/src/test/java/org/apache/streampipes/sinks/internal/jvm/datalake/migrations/DataLakeSinkMigrationV2Test.java
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.sinks.internal.jvm.datalake.migrations;
+
+import org.apache.streampipes.model.SpDataStream;
+import org.apache.streampipes.model.graph.DataSinkInvocation;
+import org.apache.streampipes.model.migration.MigrationResult;
+import org.apache.streampipes.model.schema.EventSchema;
+import org.apache.streampipes.model.schema.PropertyScope;
+import org.apache.streampipes.model.staticproperty.RuntimeResolvableAnyStaticProperty;
+import org.apache.streampipes.sdk.builder.PrimitivePropertyBuilder;
+import org.apache.streampipes.sdk.extractor.DataSinkParameterExtractor;
+import org.apache.streampipes.sdk.utils.Datatypes;
+import org.apache.streampipes.sinks.internal.jvm.datalake.DataLakeSink;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.mockito.Mockito.mock;
+
+public class DataLakeSinkMigrationV2Test {
+
+  @Test
+  public void migrate() {
+    var dataLakeSinkMigrationV2 = new DataLakeSinkMigrationV2();
+
+    var stream = new SpDataStream();
+    stream.setEventSchema(makeSchema());
+    var extractor = mock(DataSinkParameterExtractor.class);
+    var invocation = new DataSinkInvocation();
+    invocation.setStaticProperties(new ArrayList<>());
+    invocation.setInputStreams(List.of(stream));
+
+    var actual = dataLakeSinkMigrationV2.migrate(invocation, extractor);
+
+    Assertions.assertTrue(actual.success());
+    Assertions.assertEquals(actual.element()
+        .getStaticProperties()
+        .size(), 2);
+    var dimensionConfig = getAnyStaticProperty(actual);
+    Assertions.assertEquals(dimensionConfig.getInternalName(), DataLakeSink.DIMENSIONS_KEY);
+    Assertions.assertEquals(dimensionConfig.getOptions().size(), 3);
+    Assertions.assertTrue(dimensionConfig.getOptions().get(0).isSelected());
+    Assertions.assertFalse(dimensionConfig.getOptions().get(1).isSelected());
+    Assertions.assertFalse(dimensionConfig.getOptions().get(2).isSelected());
+  }
+
+  private static RuntimeResolvableAnyStaticProperty getAnyStaticProperty(MigrationResult<DataSinkInvocation> actual) {
+    return (RuntimeResolvableAnyStaticProperty) actual.element()
+        .getStaticProperties()
+        .get(0);
+  }
+
+  private static EventSchema makeSchema() {
+    return new EventSchema(
+        List.of(
+            PrimitivePropertyBuilder
+                .create(Datatypes.String, "a")
+                .scope(PropertyScope.DIMENSION_PROPERTY)
+                .build(),
+            PrimitivePropertyBuilder
+                .create(Datatypes.Float, "b")
+                .scope(PropertyScope.MEASUREMENT_PROPERTY)
+                .build(),
+            PrimitivePropertyBuilder
+                .create(Datatypes.Integer, "c")
+                .scope(PropertyScope.MEASUREMENT_PROPERTY)
+                .build(),
+            PrimitivePropertyBuilder
+                .create(Datatypes.Boolean, "d")
+                .scope(PropertyScope.MEASUREMENT_PROPERTY)
+                .build()
+        )
+    );
+  }
+}
diff --git a/streampipes-pipeline-management/src/test/java/org/apache/streampipes/manager/matching/v2/ListPropertyMatchTest.java b/streampipes-pipeline-management/src/test/java/org/apache/streampipes/manager/matching/v2/ListPropertyMatchTest.java
index 50026e5757..e84ba4c087 100644
--- a/streampipes-pipeline-management/src/test/java/org/apache/streampipes/manager/matching/v2/ListPropertyMatchTest.java
+++ b/streampipes-pipeline-management/src/test/java/org/apache/streampipes/manager/matching/v2/ListPropertyMatchTest.java
@@ -24,7 +24,6 @@ import org.apache.streampipes.model.schema.EventPropertyList;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
-import java.net.URI;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -33,13 +32,12 @@ public class ListPropertyMatchTest {
 
   @Test
   public void matchSameDomainProperty() {
-    List<URI> domainProperties = new ArrayList<>();
-    domainProperties.add(URI.create("http://test.org/property"));
+    var semanticType = "http://test.org/property";
 
     EventPropertyList offer = new EventPropertyList();
-    offer.setDomainProperties(domainProperties);
+    offer.setSemanticType(semanticType);
     EventPropertyList requirement = new EventPropertyList();
-    requirement.setDomainProperties(domainProperties);
+    requirement.setSemanticType(semanticType);
 
     List<MatchingResultMessage> errorLog = new ArrayList<>();
 
@@ -61,4 +59,4 @@ public class ListPropertyMatchTest {
     Assertions.assertTrue(result);
   }
 
-}
\ No newline at end of file
+}
diff --git a/streampipes-pipeline-management/src/test/java/org/apache/streampipes/manager/matching/v2/TestDomainPropertyMatch.java b/streampipes-pipeline-management/src/test/java/org/apache/streampipes/manager/matching/v2/TestSemanticTypeMatch.java
similarity index 63%
rename from streampipes-pipeline-management/src/test/java/org/apache/streampipes/manager/matching/v2/TestDomainPropertyMatch.java
rename to streampipes-pipeline-management/src/test/java/org/apache/streampipes/manager/matching/v2/TestSemanticTypeMatch.java
index 07038bd632..12d004b996 100644
--- a/streampipes-pipeline-management/src/test/java/org/apache/streampipes/manager/matching/v2/TestDomainPropertyMatch.java
+++ b/streampipes-pipeline-management/src/test/java/org/apache/streampipes/manager/matching/v2/TestSemanticTypeMatch.java
@@ -24,37 +24,32 @@ import org.apache.streampipes.vocabulary.Geo;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
-import java.net.URI;
 import java.util.ArrayList;
 import java.util.List;
 
-public class TestDomainPropertyMatch {
+public class TestSemanticTypeMatch {
 
   @Test
-  public void testPositiveDomainPropertyMatch() {
+  public void testPositiveSemanticTypeMatch() {
 
-    List<URI> offeredDomainProperty = buildDomainProperties(Geo.LAT);
-    List<URI> requiredDomainProperty = buildDomainProperties(Geo.LAT);
+    var offeredDomainProperty = Geo.LAT;
+    var requiredDomainProperty = Geo.LAT;
 
     List<MatchingResultMessage> resultMessage = new ArrayList<>();
 
-    boolean matches = new DomainPropertyMatch().match(offeredDomainProperty, requiredDomainProperty, resultMessage);
+    boolean matches = new SemanticTypeMatch().match(offeredDomainProperty, requiredDomainProperty, resultMessage);
     Assertions.assertTrue(matches);
   }
 
   @Test
-  public void testNegativeDomainPropertyMatch() {
+  public void testNegativeSemanticTypeMatch() {
 
-    List<URI> offeredDomainProperty = buildDomainProperties(Geo.LAT);
-    List<URI> requiredDomainProperty = buildDomainProperties(Geo.LNG);
+    var offeredDomainProperty = Geo.LAT;
+    var requiredDomainProperty = Geo.LNG;
 
     List<MatchingResultMessage> resultMessage = new ArrayList<>();
 
-    boolean matches = new DomainPropertyMatch().match(offeredDomainProperty, requiredDomainProperty, resultMessage);
+    boolean matches = new SemanticTypeMatch().match(offeredDomainProperty, requiredDomainProperty, resultMessage);
     Assertions.assertFalse(matches);
   }
-
-  private List<URI> buildDomainProperties(String name) {
-    return List.of(URI.create(name));
-  }
 }
diff --git a/streampipes-test-utils/src/main/java/org/apache/streampipes/test/generator/EventPropertyPrimitiveTestBuilder.java b/streampipes-test-utils/src/main/java/org/apache/streampipes/test/generator/EventPropertyPrimitiveTestBuilder.java
index fc5c1babc3..61439a9638 100644
--- a/streampipes-test-utils/src/main/java/org/apache/streampipes/test/generator/EventPropertyPrimitiveTestBuilder.java
+++ b/streampipes-test-utils/src/main/java/org/apache/streampipes/test/generator/EventPropertyPrimitiveTestBuilder.java
@@ -21,7 +21,6 @@ import org.apache.streampipes.model.schema.EventPropertyPrimitive;
 import org.apache.streampipes.model.schema.PropertyScope;
 
 import java.net.URI;
-import java.util.List;
 
 public class EventPropertyPrimitiveTestBuilder
     extends EventPropertyTestBuilder<EventPropertyPrimitive, EventPropertyPrimitiveTestBuilder> {
@@ -41,7 +40,7 @@ public class EventPropertyPrimitiveTestBuilder
   }
 
   public EventPropertyPrimitiveTestBuilder withSemanticType(String semanticType) {
-    this.eventProperty.setDomainProperties(List.of(URI.create(semanticType)));
+    this.eventProperty.setSemanticType(semanticType);
     return this;
   }
 
diff --git a/streampipes-test-utils/src/main/java/org/apache/streampipes/test/generator/EventStreamGenerator.java b/streampipes-test-utils/src/main/java/org/apache/streampipes/test/generator/EventStreamGenerator.java
index 97e420af86..e46e0ee1b8 100644
--- a/streampipes-test-utils/src/main/java/org/apache/streampipes/test/generator/EventStreamGenerator.java
+++ b/streampipes-test-utils/src/main/java/org/apache/streampipes/test/generator/EventStreamGenerator.java
@@ -23,7 +23,6 @@ import org.apache.streampipes.model.schema.EventSchema;
 import org.apache.streampipes.test.generator.grounding.EventGroundingGenerator;
 import org.apache.streampipes.vocabulary.XSD;
 
-import java.util.ArrayList;
 import java.util.List;
 import java.util.stream.Collectors;
 
@@ -43,7 +42,7 @@ public class EventStreamGenerator {
         .getEventSchema()
         .setEventProperties(runtimeNames
             .stream()
-            .map(r -> new EventPropertyPrimitive(XSD.INTEGER.toString(), r, "", new ArrayList<>()))
+            .map(r -> new EventPropertyPrimitive(XSD.INTEGER.toString(), r, "", ""))
             .collect(Collectors.toList()));
 
     return stream;
diff --git a/ui/cypress/tests/connect/opcua/startAndEditOpcAdapters.spec.ts b/ui/cypress/tests/connect/opcua/startAndEditOpcAdapters.spec.ts
index 0930395268..6e387b8958 100644
--- a/ui/cypress/tests/connect/opcua/startAndEditOpcAdapters.spec.ts
+++ b/ui/cypress/tests/connect/opcua/startAndEditOpcAdapters.spec.ts
@@ -51,13 +51,11 @@ describe('Test starting and editing OPC-UA Adapters in different configurations'
 
     it('Edit OPC-UA Adapter created with Tree editor', () => {
         const adapterInput = OpcUaUtils.getAdapterBuilderWithTreeNodes(true);
-
         editAdapterTest(adapterInput);
     });
 
     it('Edit OPC-UA Adapter created with Text editor', () => {
         const adapterInput = getAdapterBuilderWithTextNodes(true);
-
         editAdapterTest(adapterInput);
     });
 });
diff --git a/ui/cypress/tests/datalake/timeRangeSelectors.spec.ts b/ui/cypress/tests/datalake/timeRangeSelectors.spec.ts
index e2a8faff84..efecf9fc9b 100644
--- a/ui/cypress/tests/datalake/timeRangeSelectors.spec.ts
+++ b/ui/cypress/tests/datalake/timeRangeSelectors.spec.ts
@@ -44,11 +44,12 @@ describe('Test Time Range Selectors in Data Explorer', () => {
     before('Setup Tests', () => {
         cy.initStreamPipesTest();
         DataLakeUtils.loadDataIntoDataLake('datalake/sample.csv', false);
-        DataLakeUtils.goToDatalake();
-        DataLakeUtils.createAndEditDataView();
     });
 
     it('Perform Test', () => {
+        DataLakeUtils.goToDatalake();
+        DataLakeUtils.createAndEditDataView();
+
         periods.forEach(period => {
             cy.log('Testing period: ' + period.selector);
             DataLakeUtils.openTimeSelectorMenu();
diff --git a/ui/cypress/tests/userManagement/testGroupManagement.spec.ts b/ui/cypress/tests/userManagement/testGroupManagement.spec.ts
index ef1f45562c..2f4de9e7bf 100644
--- a/ui/cypress/tests/userManagement/testGroupManagement.spec.ts
+++ b/ui/cypress/tests/userManagement/testGroupManagement.spec.ts
@@ -123,7 +123,7 @@ describe('Test Group Management for Pipelines', () => {
 
         cy.dataCy('navigation-icon', { timeout: 10000 }).should(
             'have.length',
-            2,
+            3,
         );
 
         // Check if pipeline is invisible to user2
diff --git a/ui/cypress/tests/userManagement/testUserRolePipeline.spec.ts b/ui/cypress/tests/userManagement/testUserRolePipeline.spec.ts
index 6d4a9b9cb7..a992334de8 100644
--- a/ui/cypress/tests/userManagement/testUserRolePipeline.spec.ts
+++ b/ui/cypress/tests/userManagement/testUserRolePipeline.spec.ts
@@ -83,7 +83,7 @@ describe('Test User Roles for Pipelines', () => {
 
         cy.dataCy('navigation-icon', { timeout: 10000 }).should(
             'have.length',
-            2,
+            3,
         );
 
         PipelineUtils.goToPipelines();