Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 11 additions & 11 deletions docs/asciidoc/problem-details.adoc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
== Problem Details
=== Problem Details

Most APIs have a way to report problems and errors, helping the user understand when something went wrong and what the issue is.
The method used depends on the API’s style, technology, and design.
Expand All @@ -12,7 +12,7 @@ If it suits the API’s needs, using this standard benefits both designers and u

`Jooby` provides built-in support for `Problem Details`.

=== Set up ProblemDetails
==== Set up ProblemDetails

To enable the `ProblemDetails`, simply add the following line to your configuration:

Expand Down Expand Up @@ -44,11 +44,11 @@ problem.details {
<3> You can optionally mute some exceptions logging completely.


=== Creating problems
==== Creating problems

`HttpProblem` class represents the `RFC 7807` model. It is the main entity you need to work with to produce the problem.

==== Static helpers
===== Static helpers

There are several handy static methods to produce a simple `HttpProblem`:

Expand Down Expand Up @@ -111,7 +111,7 @@ Resulting response:
}
----

==== Builder
===== Builder

Use builder to create a rich problem instance with all properties:

Expand All @@ -126,7 +126,7 @@ throw HttpProblem.builder()
.build();
----

=== Adding extra parameters
==== Adding extra parameters

`RFC 7807` has a simple extension model: APIs are free to add any other properties to the problem details object, so all properties other than the five ones listed above are extensions.

Expand Down Expand Up @@ -163,7 +163,7 @@ Resulting response:
}
----

=== Adding headers
==== Adding headers

Some `HTTP` codes (like `413` or `426`) require additional response headers, or it may be required by third-party system/integration. `HttpProblem` support additional headers in response:

Expand All @@ -177,7 +177,7 @@ throw HttpProblem.builder()
.build();
----

=== Respond with errors details
==== Respond with errors details

`RFC 9457` finally described how errors should be delivered in HTTP APIs.
It is basically another extension `errors` on a root level. Adding errors is straight-forward using `error()` or `errors()` for bulk addition in builder:
Expand Down Expand Up @@ -214,7 +214,7 @@ In response:
If you need to enrich errors with more information feel free to extend `HttpProblem.Error` and make your custom errors model.
====

=== Custom `Exception` to `HttpProblem`
==== Custom `Exception` to `HttpProblem`

Apparently, you may already have many custom `Exception` classes in the codebase, and you want to make them `Problem Details` compliant without complete re-write. You can achieve this by implementing `HttpProblemMappable` interface. It allows you to control how exceptions should be transformed into `HttpProblem` if default behaviour doesn't suite your needs:

Expand All @@ -233,7 +233,7 @@ public class MyException implements HttpProblemMappable {
}
----

=== Custom Problems
==== Custom Problems

Extending `HttpProblem` and utilizing builder functionality makes it really easy:

Expand All @@ -255,7 +255,7 @@ public class OutOfStockProblem extends HttpProblem {
}
----

=== Custom Exception Handlers
==== Custom Exception Handlers

All the features described above should give you ability to rely solely on built-in global error handler. But, in case you still need custom exception handler for some reason, you still can do it:

Expand Down
50 changes: 50 additions & 0 deletions docs/asciidoc/routing.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -1362,6 +1362,56 @@ Output:

Done {love}!

=== Multiple routers

This model let you `run` multiple applications on single server instance. Each application
works like a standalone application, they don't share any kind of services.

.Multiple routers
[source, java,role="primary"]
----
public class Foo extends Jooby {
{
setContextPath("/foo");
get("/hello", ctx -> ...);
}
}

public class Bar extends Jooby {
{
setContextPath("/bar");
get("/hello", ctx -> ...);
}
}

import static io.jooby.Jooby.runApp;

public class MultiApp {
public static void main(String[] args) {
runApp(args, List.of(Foo::new, Bar::new));
}
}
----

.Kotlin
[source, kotlin,role="secondary"]
----

import io.jooby.kt.Kooby.runApp

fun main(args: Array<String>) {
runApp(args, ::Foo, ::Bar)
}
----

You write your application as always and them you deploy them using the `runApp` method.

[IMPORTANT]
====
Due to nature of logging framework (static loading and initialization) the logging bootstrap
might not work as you expected. It is recommend to use just the `logback.xml` or `log4j.xml` file.
====

=== Options

include::router-hidden-method.adoc[]
Expand Down
8 changes: 4 additions & 4 deletions docs/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

<properties>
<application.class>io.jooby.adoc.DocApp</application.class>
<jooby.version>3.2.0</jooby.version>
<jooby.version>3.7.0</jooby.version>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<maven.compiler.release>17</maven.compiler.release>
Expand All @@ -20,7 +20,7 @@
<dependencies>
<dependency>
<groupId>io.jooby</groupId>
<artifactId>jooby-undertow</artifactId>
<artifactId>jooby-netty</artifactId>
<version>${jooby.version}</version>
</dependency>

Expand Down Expand Up @@ -51,7 +51,7 @@
<dependency>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctorj</artifactId>
<version>2.5.7</version>
<version>3.0.0</version>
</dependency>

<dependency>
Expand All @@ -63,7 +63,7 @@
<dependency>
<groupId>io.methvin</groupId>
<artifactId>directory-watcher</artifactId>
<version>0.18.0</version>
<version>0.19.0</version>
</dependency>

<!-- zt-exec -->
Expand Down
51 changes: 25 additions & 26 deletions docs/src/main/java/io/jooby/adoc/DocGenerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -251,30 +251,30 @@ private static void processModule(

private static Options createOptions(Path basedir, Path outdir, String version, String title)
throws IOException {
Attributes attributes = new Attributes();
var attributes = Attributes.builder();

attributes.setAttribute("love", "&#9825;");
attributes.setAttribute("docinfo", "shared");
attributes.setTitle(title == null ? "jooby: do more! more easily!!" : "jooby: " + title);
attributes.setTableOfContents(Placement.LEFT);
attributes.setAttribute("toclevels", "3");
attributes.attribute("love", "&#9825;");
attributes.attribute("docinfo", "shared");
attributes.title(title == null ? "jooby: do more! more easily!!" : "jooby: " + title);
attributes.tableOfContents(Placement.LEFT);
attributes.attribute("toclevels", "3");
attributes.setAnchors(true);
attributes.setAttribute("sectlinks", "");
attributes.setSectionNumbers(true);
attributes.setAttribute("sectnumlevels", "3");
attributes.setLinkAttrs(true);
attributes.setNoFooter(true);
attributes.setAttribute("idprefix", "");
attributes.setAttribute("idseparator", "-");
attributes.setIcons("font");
attributes.setAttribute("description", "The modular micro web framework for Java");
attributes.setAttribute(
attributes.attribute("sectlinks", "");
attributes.sectionNumbers(true);
attributes.attribute("sectnumlevels", "3");
attributes.linkAttrs(true);
attributes.noFooter(true);
attributes.attribute("idprefix", "");
attributes.attribute("idseparator", "-");
attributes.icons("font");
attributes.attribute("description", "The modular micro web framework for Java");
attributes.attribute(
"keywords", "Java, Modern, Micro, Web, Framework, Reactive, Lightweight, Microservices");
attributes.setImagesDir("images");
attributes.setSourceHighlighter("highlightjs");
attributes.setAttribute("highlightjsdir", "js");
attributes.setAttribute("highlightjs-theme", "agate");
attributes.setAttribute("favicon", "images/favicon96.png");
attributes.imagesDir("images");
attributes.sourceHighlighter("highlightjs");
attributes.attribute("highlightjsdir", "js");
attributes.attribute("highlightjs-theme", "agate");
attributes.attribute("favicon", "images/favicon96.png");

// versions:
Document pom =
Expand All @@ -283,21 +283,20 @@ private static Options createOptions(Path basedir, Path outdir, String version,
var tagName = tag.tagName();
var value = tag.text().trim();
Stream.of(tagName, tagName.replaceAll("[.-]", "_"), tagName.replaceAll("[.-]", "-"), toJavaName(tagName))
.forEach(key -> attributes.setAttribute(key, value));
.forEach(key -> attributes.attribute(key, value));
});

attributes.setAttribute("joobyVersion", version);
attributes.setAttribute("date", DateTimeFormatter.ISO_INSTANT.format(Instant.now()));
attributes.attribute("joobyVersion", version);
attributes.attribute("date", DateTimeFormatter.ISO_INSTANT.format(Instant.now()));

OptionsBuilder options = Options.builder();
options.backend("html");

options.attributes(attributes);
options.attributes(attributes.build());
options.baseDir(basedir.toAbsolutePath().toFile());
options.docType("book");
options.toDir(outdir.toFile());
options.mkDirs(true);
options.destinationDir(outdir.resolve("site").toFile());
options.safe(SafeMode.UNSAFE);
return options.build();
}
Expand Down
5 changes: 3 additions & 2 deletions docs/src/main/java/io/jooby/adoc/JavadocProcessor.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
import java.util.stream.Collectors;

import org.asciidoctor.ast.ContentNode;
import org.asciidoctor.ast.PhraseNode;
import org.asciidoctor.ast.StructuralNode;
import org.asciidoctor.extension.InlineMacroProcessor;

public class JavadocProcessor extends InlineMacroProcessor {
Expand All @@ -22,8 +24,7 @@ public JavadocProcessor(String name) {
}

@Override
public Object process(ContentNode parent, String clazz, Map<String, Object> attributes) {

public PhraseNode process(StructuralNode parent, String clazz, Map<String, Object> attributes) {
StringBuilder link =
new StringBuilder("https://www.javadoc.io/doc/io.jooby/jooby/latest/io.jooby/io/jooby/");
StringBuilder text = new StringBuilder();
Expand Down
41 changes: 41 additions & 0 deletions jooby/src/main/java/io/jooby/Context.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,47 @@
*/
public interface Context extends Registry {

/** Select an application base on context path prefix matching a provided path. */
interface Selector {
/**
* Select an application base on context path prefix matching a provided path.
*
* @param applications List of applications.
* @param path Path to match.
* @return Best match application.
*/
Jooby select(List<Jooby> applications, String path);

static Selector create(List<Jooby> applications) {
return applications.size() == 1 ? single() : multiple();
}

/**
* Select an application the best match a given path. If none matches it returns the application
* that has no context path <code>/</code> or the first of the list.
*
* @return Best match application.
*/
static Selector multiple() {
return (applications, path) -> {
var defaultApp = applications.get(0);
for (var app : applications) {
var contextPath = app.getContextPath();
if ("/".equals(contextPath)) {
defaultApp = app;
} else if (path.startsWith(contextPath)) {
return app;
}
}
return defaultApp;
};
}

private static Selector single() {
return (applications, path) -> applications.get(0);
}
}

/** Constant for default HTTP port. */
int PORT = 80;

Expand Down
Loading