# Custom Code Regions in Java

To enable custom code regions for Java SDKs, update the project's
`.speakeasy/gen.yaml` file as follows:

```diff filename=".speakeasy/gen.yaml"
configVersion: 2.0.0
generation:
  # ...
java:
  # ...
+ enableCustomCodeRegions: true
```

## Full example

The Speakeasy examples repository includes a [full Java SDK](https://github.com/speakeasy-api/examples/tree/main/customcode-sdkclasses-java) that uses custom code regions.

## Regions

Below are the available code regions in Java SDKs.

### SDK classes

Java SDK classes can have two code regions:

- `// #region imports`: The imports region allows you to add imports to an SDK file needed for
  custom methods and properties. It must be located at the top of the
  file alongside generated imports.
- `// #region class-body`: The class-body region allows you to add custom methods and
  properties to an SDK class. It must be located in the body of a Java
  SDK class alongside generated methods and properties.

### Model classes

Java model classes can also have custom code regions:

- `// #region imports`: The imports region allows you to add imports to a model file needed for
  custom methods and properties. It must be located at the top of the
  file alongside generated imports.
- `// #region class-body`: The class-body region allows you to add custom methods and
  properties to a model class. It must be located in the body of a Java
  model class alongside generated methods and properties.

## Managing dependencies

When adding custom code that requires external packages, configure these dependencies in the `.speakeasy/gen.yaml` file to prevent them from being removed during SDK regeneration. Use the `additionalDependencies` configuration to specify package dependencies:

```yaml filename=".speakeasy/gen.yaml"
java:
  additionalDependencies:
    - implementation:org.commonmark:commonmark:0.21.0
    - implementation:org.jsoup:jsoup:1.16.1
    - testImplementation:org.junit.jupiter:junit-jupiter:5.9.2
    - testImplementation:org.mockito:mockito-core:5.1.1
```

This ensures that dependencies persist across SDK regenerations and are properly included in the generated `build.gradle`.

```java filename="src/main/java/com/example/sdk/Todos.java"
/*
 * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.
 */

package com.example.sdk;

// #region imports

// #endregion imports

public class Todos implements
            MethodCallCreate,
            MethodCallGetOne {

    private final SDKConfiguration sdkConfiguration;

    Todos(SDKConfiguration sdkConfiguration) {
        this.sdkConfiguration = sdkConfiguration;
    }

    // #region class-body
    public String renderTodo(String id) throws Exception {
        Todo todo = getOne(id).todo()
            .orElseThrow(() -> new Exception("Todo not found"));

        Parser parser = Parser.builder().build();
        HtmlRenderer renderer = HtmlRenderer.builder().build();

        String markdown = String.format("# %s\n\n%s", todo.title(), todo.description());

        return renderer.render(parser.parse(markdown));
    }
    // #endregion class-body

    public Todo getOne(String id) throws Exception {
        // Generated method implementation
        ...
    }
}
```

## Model class example

You can also add custom methods to model classes. This example adds a `render()` method to a `Todo` model class:

```java filename="src/main/java/com/example/sdk/models/components/Todo.java"
/*
 * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.
 */

package com.example.sdk.models.components;

// #region imports

// #endregion imports

public class Todo {

    @JsonProperty("id")
    private String id;

    @JsonProperty("title")
    private String title;

    @JsonProperty("description")
    private String description;

    @JsonProperty("completed")
    private boolean completed;

    @JsonCreator
    public Todo(
            @JsonProperty("id") String id,
            @JsonProperty("title") String title,
            @JsonProperty("description") String description,
            @JsonProperty("completed") boolean completed) {
        Utils.checkNotNull(id, "id");
        Utils.checkNotNull(title, "title");
        Utils.checkNotNull(description, "description");
        Utils.checkNotNull(completed, "completed");
        this.id = id;
        this.title = title;
        this.description = description;
        this.completed = completed;
    }

    @JsonIgnore
    public String id() {
        return id;
    }

    @JsonIgnore
    public String title() {
        return title;
    }

    @JsonIgnore
    public String description() {
        return description;
    }

    @JsonIgnore
    public boolean completed() {
        return completed;
    }

    // #region class-body
    public String render() throws Exception {
        Parser parser = Parser.builder().build();
        HtmlRenderer renderer = HtmlRenderer.builder().build();
        String markdown = String.format("# %s\n\n%s", title(), description());

        return renderer.render(parser.parse(markdown));
    }
    // #endregion class-body

    // Generated methods continue...
}
```

This allows you to use the custom method as follows:

```java
Todo todo = ...;
String rendered = todo.render();
```
