Move Docker Compose and Testcontainers to separate section

See gh-38361
This commit is contained in:
Moritz Halbritter 2024-04-17 14:05:52 +02:00
parent dfee56ad9d
commit 00a10fdc52
15 changed files with 163 additions and 151 deletions

View File

@ -1038,15 +1038,15 @@
* xref:reference:features/developing-auto-configuration.adoc#features.developing-auto-configuration.testing.overriding-classpath[#features.developing-auto-configuration.testing.overriding-classpath]
* xref:reference:features/developing-auto-configuration.adoc#features.developing-auto-configuration.testing.simulating-a-web-context[#features.developing-auto-configuration.testing.simulating-a-web-context]
* xref:reference:features/developing-auto-configuration.adoc#features.developing-auto-configuration.understanding-auto-configured-beans[#features.developing-auto-configuration.understanding-auto-configured-beans]
* xref:reference:features/docker-compose.adoc#features.docker-compose[#features.docker-compose]
* xref:reference:features/docker-compose.adoc#features.docker-compose.custom-images[#features.docker-compose.custom-images]
* xref:reference:features/docker-compose.adoc#features.docker-compose.lifecycle[#features.docker-compose.lifecycle]
* xref:reference:features/docker-compose.adoc#features.docker-compose.prerequisites[#features.docker-compose.prerequisites]
* xref:reference:features/docker-compose.adoc#features.docker-compose.profiles[#features.docker-compose.profiles]
* xref:reference:features/docker-compose.adoc#features.docker-compose.readiness[#features.docker-compose.readiness]
* xref:reference:features/docker-compose.adoc#features.docker-compose.service-connections[#features.docker-compose.service-connections]
* xref:reference:features/docker-compose.adoc#features.docker-compose.skipping[#features.docker-compose.skipping]
* xref:reference:features/docker-compose.adoc#features.docker-compose.specific-file[#features.docker-compose.specific-file]
* xref:reference:features/dev-services.adoc#features.dev-services.docker-compose[#features.docker-compose]
* xref:reference:features/dev-services.adoc#features.dev-services.docker-compose.custom-images[#features.docker-compose.custom-images]
* xref:reference:features/dev-services.adoc#features.dev-services.docker-compose.lifecycle[#features.docker-compose.lifecycle]
* xref:reference:features/dev-services.adoc#features.dev-services.docker-compose.prerequisites[#features.docker-compose.prerequisites]
* xref:reference:features/dev-services.adoc#features.dev-services.docker-compose.profiles[#features.docker-compose.profiles]
* xref:reference:features/dev-services.adoc#features.dev-services.docker-compose.readiness[#features.docker-compose.readiness]
* xref:reference:features/dev-services.adoc#features.dev-services.docker-compose.service-connections[#features.docker-compose.service-connections]
* xref:reference:features/dev-services.adoc#features.dev-services.docker-compose.skipping[#features.docker-compose.skipping]
* xref:reference:features/dev-services.adoc#features.dev-services.docker-compose.specific-file[#features.docker-compose.specific-file]
* xref:reference:features/external-config.adoc#features.external-config[#features.external-config]
* xref:reference:features/external-config.adoc#features.external-config.application-json[#features.external-config.application-json]
* xref:reference:features/external-config.adoc#features.external-config.command-line-args[#features.external-config.command-line-args]
@ -1154,11 +1154,11 @@
* xref:reference:features/ssl.adoc#features.ssl.pem[#features.ssl.pem]
* xref:reference:features/ssl.adoc#features.ssl.reloading[#features.ssl.reloading]
* xref:reference:features/task-execution-and-scheduling.adoc#features.task-execution-and-scheduling[#features.task-execution-and-scheduling]
* xref:reference:features/testcontainers.adoc#features.testcontainers[#features.testcontainers]
* xref:reference:features/testcontainers.adoc#features.testcontainers.at-development-time[#features.testcontainers.at-development-time]
* xref:reference:features/testcontainers.adoc#features.testcontainers.at-development-time.devtools[#features.testcontainers.at-development-time.devtools]
* xref:reference:features/testcontainers.adoc#features.testcontainers.at-development-time.dynamic-properties[#features.testcontainers.at-development-time.dynamic-properties]
* xref:reference:features/testcontainers.adoc#features.testcontainers.at-development-time.importing-container-declarations[#features.testcontainers.at-development-time.importing-container-declarations]
* xref:reference:features/dev-services.adoc#features.dev-services.testcontainers[#features.testcontainers]
* xref:reference:features/dev-services.adoc#features.dev-services.testcontainers.at-development-time[#features.testcontainers.at-development-time]
* xref:reference:features/dev-services.adoc#features.dev-services.testcontainers.at-development-time.devtools[#features.testcontainers.at-development-time.devtools]
* xref:reference:features/dev-services.adoc#features.dev-services.testcontainers.at-development-time.dynamic-properties[#features.testcontainers.at-development-time.dynamic-properties]
* xref:reference:features/dev-services.adoc#features.dev-services.testcontainers.at-development-time.importing-container-declarations[#features.testcontainers.at-development-time.importing-container-declarations]
* xref:reference:features/testing.adoc#features.testing[#features.testing]
* xref:reference:features/testing.adoc#features.testing.spring-applications[#features.testing.spring-applications]
* xref:reference:features/testing.adoc#features.testing.spring-boot-applications[#features.testing.spring-boot-applications]

View File

@ -1,5 +1,14 @@
[[features.docker-compose]]
= Docker Compose Support
[[features.dev-services]]
= Development-time services
Development-time services provide external dependencies needed to run the application while developing it.
They are only supposed to be used while developing and are disabled when the application is deployed.
Spring Boot offers support for two development time services, Docker Compose and Testcontainers.
The next sections will provide more details about them.
[[features.dev-services.docker-compose]]
== Docker Compose Support
Docker Compose is a popular technology that can be used to define and manage multiple containers for services that your application needs.
A `compose.yml` file is typically created next to your application which defines and configures service containers.
@ -44,16 +53,16 @@ To enable it, set configprop:spring.docker.compose.skip.in-tests[] to `false`.
[[features.docker-compose.prerequisites]]
== Prerequisites
[[features.dev-services.docker-compose.prerequisites]]
=== Prerequisites
You need to have the `docker` and `docker compose` (or `docker-compose`) CLI applications on your path.
The minimum supported Docker Compose version is 2.2.0.
[[features.docker-compose.service-connections]]
== Service Connections
[[features.dev-services.docker-compose.service-connections]]
=== Service Connections
A service connection is a connection to any remote service.
Spring Boots auto-configuration can consume the details of a service connection and use them to establish a connection to a remote service.
@ -120,8 +129,8 @@ The following service connections are currently supported:
[[features.docker-compose.custom-images]]
== Custom Images
[[features.dev-services.docker-compose.custom-images]]
=== Custom Images
Sometimes you may need to use your own version of an image to provide a service.
You can use any custom image as long as it behaves in the same way as the standard image.
@ -145,8 +154,8 @@ services:
[[features.docker-compose.skipping]]
== Skipping Specific Containers
[[features.dev-services.docker-compose.skipping]]
=== Skipping Specific Containers
If you have a container image defined in your `compose.yml` that you dont want connected to your application you can use a label to ignore it.
Any container with labeled with `org.springframework.boot.ignore` will be ignored by Spring Boot.
@ -166,8 +175,8 @@ services:
[[features.docker-compose.specific-file]]
== Using a Specific Compose File
[[features.dev-services.docker-compose.specific-file]]
=== Using a Specific Compose File
If your compose file is not in the same directory as your application, or if its named differently, you can use configprop:spring.docker.compose.file[] in your `application.properties` or `application.yaml` to point to a different file.
Properties can be defined as an exact path or a path thats relative to your application.
@ -184,8 +193,8 @@ spring:
[[features.docker-compose.readiness]]
== Waiting for Container Readiness
[[features.dev-services.docker-compose.readiness]]
=== Waiting for Container Readiness
Containers started by Docker Compose may take some time to become fully ready.
The recommended way of checking for readiness is to add a `healthcheck` section under the service definition in your `compose.yml` file.
@ -225,8 +234,8 @@ The overall timeout can be configured using configprop:spring.docker.compose.rea
[[features.docker-compose.lifecycle]]
== Controlling the Docker Compose Lifecycle
[[features.dev-services.docker-compose.lifecycle]]
=== Controlling the Docker Compose Lifecycle
By default Spring Boot calls `docker compose up` when your application starts and `docker compose stop` when it's shut down.
If you prefer to have different lifecycle management you can use the configprop:spring.docker.compose.lifecycle-management[] property.
@ -257,8 +266,8 @@ spring:
[[features.docker-compose.profiles]]
== Activating Docker Compose Profiles
[[features.dev-services.docker-compose.profiles]]
=== Activating Docker Compose Profiles
Docker Compose profiles are similar to Spring profiles in that they let you adjust your Docker Compose configuration for specific environments.
If you want to activate a specific Docker Compose profile you can use the configprop:spring.docker.compose.profiles.active[] property in your `application.properties` or `application.yaml` file:
@ -271,3 +280,104 @@ spring:
profiles:
active: "myprofile"
----
[[features.dev-services.testcontainers]]
== Testcontainers Support
As well as xref:features/testing.adoc#features.testing.testcontainers[using Testcontainers for integration testing], it's also possible to use them at development time.
The next sections will provide more details about that.
[[features.dev-services.testcontainers.at-development-time]]
=== Using Testcontainers at Development Time
This approach allows developers to quickly start containers for the services that the application depends on, removing the need to manually provision things like database servers.
Using Testcontainers in this way provides functionality similar to Docker Compose, except that your container configuration is in Java rather than YAML.
To use Testcontainers at development time you need to launch your application using your "`test`" classpath rather than "`main`".
This will allow you to access all declared test dependencies and give you a natural place to write your test configuration.
To create a test launchable version of your application you should create an "`Application`" class in the `src/test` directory.
For example, if your main application is in `src/main/java/com/example/MyApplication.java`, you should create `src/test/java/com/example/TestMyApplication.java`
The `TestMyApplication` class can use the `SpringApplication.from(...)` method to launch the real application:
include-code::launch/TestMyApplication[]
You'll also need to define the `Container` instances that you want to start along with your application.
To do this, you need to make sure that the `spring-boot-testcontainers` module has been added as a `test` dependency.
Once that has been done, you can create a `@TestConfiguration` class that declares `@Bean` methods for the containers you want to start.
You can also annotate your `@Bean` methods with `@ServiceConnection` in order to create `ConnectionDetails` beans.
See xref:features/testing.adoc#features.testing.testcontainers.service-connections[the service connections] section for details of the supported technologies.
A typical Testcontainers configuration would look like this:
include-code::test/MyContainersConfiguration[]
NOTE: The lifecycle of `Container` beans is automatically managed by Spring Boot.
Containers will be started and stopped automatically.
TIP: You can use the configprop:spring.testcontainers.beans.startup[] property to change how containers are started.
By default `sequential` startup is used, but you may also choose `parallel` if you wish to start multiple containers in parallel.
Once you have defined your test configuration, you can use the `with(...)` method to attach it to your test launcher:
include-code::test/TestMyApplication[]
You can now launch `TestMyApplication` as you would any regular Java `main` method application to start your application and the containers that it needs to run.
TIP: You can use the Maven goal `spring-boot:test-run` or the Gradle task `bootTestRun` to do this from the command line.
[[features.dev-services.testcontainers.at-development-time.dynamic-properties]]
==== Contributing Dynamic Properties at Development Time
If you want to contribute dynamic properties at development time from your `Container` `@Bean` methods, you can do so by injecting a `DynamicPropertyRegistry`.
This works in a similar way to the xref:features/testing.adoc#features.testing.testcontainers.dynamic-properties[`@DynamicPropertySource` annotation] that you can use in your tests.
It allows you to add properties that will become available once your container has started.
A typical configuration would look like this:
include-code::MyContainersConfiguration[]
NOTE: Using a `@ServiceConnection` is recommended whenever possible, however, dynamic properties can be a useful fallback for technologies that don't yet have `@ServiceConnection` support.
[[features.dev-services.testcontainers.at-development-time.importing-container-declarations]]
==== Importing Testcontainer Declaration Classes
A common pattern when using Testcontainers is to declare `Container` instances as static fields.
Often these fields are defined directly on the test class.
They can also be declared on a parent class or on an interface that the test implements.
For example, the following `MyContainers` interface declares `mongo` and `neo4j` containers:
include-code::MyContainers[]
If you already have containers defined in this way, or you just prefer this style, you can import these declaration classes rather than defining you containers as `@Bean` methods.
To do so, add the `@ImportTestcontainers` annotation to your test configuration class:
include-code::MyContainersConfiguration[]
TIP: If you don't intend to use the xref:features/testing.adoc#features.testing.testcontainers.service-connections[service connections feature] but want to use xref:features/testing.adoc#features.testing.testcontainers.dynamic-properties[`@DynamicPropertySource`] instead, remove the `@ServiceConnection` annotation from the `Container` fields.
You can also add `@DynamicPropertySource` annotated methods to your declaration class.
[[features.dev-services.testcontainers.at-development-time.devtools]]
==== Using DevTools with Testcontainers at Development Time
When using devtools, you can annotate beans and bean methods with `@RestartScope`.
Such beans won't be recreated when the devtools restart the application.
This is especially useful for Testcontainer `Container` beans, as they keep their state despite the application restart.
include-code::MyContainersConfiguration[]
WARNING: If you're using Gradle and want to use this feature, you need to change the configuration of the `spring-boot-devtools` dependency from `developmentOnly` to `testAndDevelopmentOnly`.
With the default scope of `developmentOnly`, the `bootTestRun` task will not pick up changes in your code, as the devtools are not active.

View File

@ -1,98 +0,0 @@
[[features.testcontainers]]
= Testcontainers Support
As well as xref:features/testing.adoc#features.testing.testcontainers[using Testcontainers for integration testing], it's also possible to use them at development time.
The next sections will provide more details about that.
[[features.testcontainers.at-development-time]]
== Using Testcontainers at Development Time
This approach allows developers to quickly start containers for the services that the application depends on, removing the need to manually provision things like database servers.
Using Testcontainers in this way provides functionality similar to Docker Compose, except that your container configuration is in Java rather than YAML.
To use Testcontainers at development time you need to launch your application using your "`test`" classpath rather than "`main`".
This will allow you to access all declared test dependencies and give you a natural place to write your test configuration.
To create a test launchable version of your application you should create an "`Application`" class in the `src/test` directory.
For example, if your main application is in `src/main/java/com/example/MyApplication.java`, you should create `src/test/java/com/example/TestMyApplication.java`
The `TestMyApplication` class can use the `SpringApplication.from(...)` method to launch the real application:
include-code::launch/TestMyApplication[]
You'll also need to define the `Container` instances that you want to start along with your application.
To do this, you need to make sure that the `spring-boot-testcontainers` module has been added as a `test` dependency.
Once that has been done, you can create a `@TestConfiguration` class that declares `@Bean` methods for the containers you want to start.
You can also annotate your `@Bean` methods with `@ServiceConnection` in order to create `ConnectionDetails` beans.
See xref:features/testing.adoc#features.testing.testcontainers.service-connections[the service connections] section for details of the supported technologies.
A typical Testcontainers configuration would look like this:
include-code::test/MyContainersConfiguration[]
NOTE: The lifecycle of `Container` beans is automatically managed by Spring Boot.
Containers will be started and stopped automatically.
TIP: You can use the configprop:spring.testcontainers.beans.startup[] property to change how containers are started.
By default `sequential` startup is used, but you may also choose `parallel` if you wish to start multiple containers in parallel.
Once you have defined your test configuration, you can use the `with(...)` method to attach it to your test launcher:
include-code::test/TestMyApplication[]
You can now launch `TestMyApplication` as you would any regular Java `main` method application to start your application and the containers that it needs to run.
TIP: You can use the Maven goal `spring-boot:test-run` or the Gradle task `bootTestRun` to do this from the command line.
[[features.testcontainers.at-development-time.dynamic-properties]]
=== Contributing Dynamic Properties at Development Time
If you want to contribute dynamic properties at development time from your `Container` `@Bean` methods, you can do so by injecting a `DynamicPropertyRegistry`.
This works in a similar way to the xref:features/testing.adoc#features.testing.testcontainers.dynamic-properties[`@DynamicPropertySource` annotation] that you can use in your tests.
It allows you to add properties that will become available once your container has started.
A typical configuration would look like this:
include-code::MyContainersConfiguration[]
NOTE: Using a `@ServiceConnection` is recommended whenever possible, however, dynamic properties can be a useful fallback for technologies that don't yet have `@ServiceConnection` support.
[[features.testcontainers.at-development-time.importing-container-declarations]]
=== Importing Testcontainer Declaration Classes
A common pattern when using Testcontainers is to declare `Container` instances as static fields.
Often these fields are defined directly on the test class.
They can also be declared on a parent class or on an interface that the test implements.
For example, the following `MyContainers` interface declares `mongo` and `neo4j` containers:
include-code::MyContainers[]
If you already have containers defined in this way, or you just prefer this style, you can import these declaration classes rather than defining you containers as `@Bean` methods.
To do so, add the `@ImportTestcontainers` annotation to your test configuration class:
include-code::MyContainersConfiguration[]
TIP: If you don't intend to use the xref:features/testing.adoc#features.testing.testcontainers.service-connections[service connections feature] but want to use xref:features/testing.adoc#features.testing.testcontainers.dynamic-properties[`@DynamicPropertySource`] instead, remove the `@ServiceConnection` annotation from the `Container` fields.
You can also add `@DynamicPropertySource` annotated methods to your declaration class.
[[features.testcontainers.at-development-time.devtools]]
=== Using DevTools with Testcontainers at Development Time
When using devtools, you can annotate beans and bean methods with `@RestartScope`.
Such beans won't be recreated when the devtools restart the application.
This is especially useful for Testcontainer `Container` beans, as they keep their state despite the application restart.
include-code::MyContainersConfiguration[]
WARNING: If you're using Gradle and want to use this feature, you need to change the configuration of the `spring-boot-devtools` dependency from `developmentOnly` to `testAndDevelopmentOnly`.
With the default scope of `developmentOnly`, the `bootTestRun` task will not pick up changes in your code, as the devtools are not active.

View File

@ -20,8 +20,7 @@
*** xref:reference:features/json.adoc[]
*** xref:reference:features/task-execution-and-scheduling.adoc[]
*** xref:reference:features/testing.adoc[]
*** xref:reference:features/docker-compose.adoc[]
*** xref:reference:features/testcontainers.adoc[]
*** xref:reference:features/dev-services.adoc[]
*** xref:reference:features/developing-auto-configuration.adoc[]
*** xref:reference:features/kotlin.adoc[]
*** xref:reference:features/ssl.adoc[]

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2023 the original author or authors.
* Copyright 2012-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.boot.docs.features.testcontainers.atdevelopmenttime.devtools;
package org.springframework.boot.docs.features.devservices.testcontainers.atdevelopmenttime.devtools;
import org.testcontainers.containers.MongoDBContainer;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2023 the original author or authors.
* Copyright 2012-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.boot.docs.features.testcontainers.atdevelopmenttime.dynamicproperties;
package org.springframework.boot.docs.features.devservices.testcontainers.atdevelopmenttime.dynamicproperties;
import org.testcontainers.containers.MongoDBContainer;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2023 the original author or authors.
* Copyright 2012-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.boot.docs.features.testcontainers.atdevelopmenttime.importingcontainerdeclarations;
package org.springframework.boot.docs.features.devservices.testcontainers.atdevelopmenttime.importingcontainerdeclarations;
import org.testcontainers.containers.MongoDBContainer;
import org.testcontainers.containers.Neo4jContainer;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2023 the original author or authors.
* Copyright 2012-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.boot.docs.features.testcontainers.atdevelopmenttime.importingcontainerdeclarations;
package org.springframework.boot.docs.features.devservices.testcontainers.atdevelopmenttime.importingcontainerdeclarations;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.testcontainers.context.ImportTestcontainers;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2023 the original author or authors.
* Copyright 2012-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.boot.docs.features.testcontainers.atdevelopmenttime.test;
package org.springframework.boot.docs.features.devservices.testcontainers.atdevelopmenttime.launch;
public class MyApplication {

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2023 the original author or authors.
* Copyright 2012-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.boot.docs.features.testcontainers.atdevelopmenttime.launch;
package org.springframework.boot.docs.features.devservices.testcontainers.atdevelopmenttime.launch;
import org.springframework.boot.SpringApplication;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2023 the original author or authors.
* Copyright 2012-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.boot.docs.features.testcontainers.atdevelopmenttime.launch;
package org.springframework.boot.docs.features.devservices.testcontainers.atdevelopmenttime.test;
public class MyApplication {

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2023 the original author or authors.
* Copyright 2012-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.boot.docs.features.testcontainers.atdevelopmenttime.test;
package org.springframework.boot.docs.features.devservices.testcontainers.atdevelopmenttime.test;
import org.testcontainers.containers.Neo4jContainer;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2023 the original author or authors.
* Copyright 2012-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.boot.docs.features.testcontainers.atdevelopmenttime.test;
package org.springframework.boot.docs.features.devservices.testcontainers.atdevelopmenttime.test;
import org.springframework.boot.SpringApplication;

View File

@ -16,6 +16,7 @@
package org.springframework.boot.docs.features.testcontainers.atdevelopmenttime.importingcontainerdeclarations
import org.springframework.boot.docs.features.devservices.testcontainers.atdevelopmenttime.importingcontainerdeclarations.MyContainers
import org.springframework.boot.test.context.TestConfiguration
import org.springframework.boot.testcontainers.context.ImportTestcontainers

View File

@ -55,7 +55,7 @@ In order to be consistent with the `repackage` goal, the `run` goal builds the c
For more details, see xref:packaging.adoc#packaging.examples.exclude-dependency[the dedicated example].
Sometimes it is useful to run a test variant of your application.
For example, if you want to xref:reference:features/testcontainers.adoc#features.testcontainers.at-development-time[use Testcontainers at development time] or make use of some test stubs.
For example, if you want to xref:reference:features/dev-services.adoc#features.dev-services.testcontainers.at-development-time[use Testcontainers at development time] or make use of some test stubs.
Use the `test-run` goal with many of the same features and configuration options as `run` for this purpose.
include::partial$goals/run.adoc[leveloffset=+1]