repository) {
+ super(repository);
+ }
+
+ /**
+ * Find the baz by name.
+ *
+ * This is some more comments about this method.
+ *
+ * @return The list of baz
+ */
+ @Get("findbyname/{name}")
+ List searchByName(String name) {
+
+ Baz b1 = new Baz();
+ b1.id = 1L;
+ b1.name = "baz1-" + name;
+
+ Baz b2 = new Baz();
+ b2.id = 2L;
+ b2.name = "baz2";
+
+ return Arrays.asList(b1, b2);
+ }
+
+ @Get("checkparams/{id}")
+ String checkParams(int id, String p1, Double p2, Integer p3, Float p4, String body) {
+ return "dummy-response";
+ }
+}
diff --git a/tests/test-sigma/src/main/java/org/example/myapp/web/GetBeanForm.java b/tests/test-sigma/src/main/java/org/example/myapp/web/GetBeanForm.java
new file mode 100644
index 000000000..70818500d
--- /dev/null
+++ b/tests/test-sigma/src/main/java/org/example/myapp/web/GetBeanForm.java
@@ -0,0 +1,88 @@
+package org.example.myapp.web;
+
+import java.util.List;
+import java.util.Set;
+
+import io.avaje.http.api.Header;
+import io.avaje.http.api.Ignore;
+import io.avaje.http.api.QueryParam;
+import io.avaje.jsonb.Json;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.Email;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Size;
+
+@Json
+@Valid
+public class GetBeanForm {
+
+ @NotNull
+ @Size(min = 2, max = 150)
+ private String name;
+
+ @Email
+ @Size(max = 100)
+ private String email;
+
+ private List addresses;
+
+ @Header private String head;
+
+ @QueryParam private Set type;
+
+ @Json.Ignore @Ignore private String ignored;
+
+ public String getIgnored() {
+ return ignored;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getEmail() {
+ return email;
+ }
+
+ public void setEmail(String email) {
+ this.email = email;
+ }
+
+ public GetBeanForm(String name, String email) {
+ this.name = name;
+ this.email = email;
+ }
+
+ @Override
+ public String toString() {
+ return "HelloForm{" + "name='" + name + '\'' + ", email='" + email + '\'' + '}';
+ }
+
+ public List getAddresses() {
+ return addresses;
+ }
+
+ public void setAddresses(List addresses) {
+ this.addresses = addresses;
+ }
+
+ public String getHead() {
+ return head;
+ }
+
+ public void setHead(String head) {
+ this.head = head;
+ }
+
+ public Set getType() {
+ return type;
+ }
+
+ public void setType(Set type) {
+ this.type = type;
+ }
+}
diff --git a/tests/test-sigma/src/main/java/org/example/myapp/web/Hallo.java b/tests/test-sigma/src/main/java/org/example/myapp/web/Hallo.java
new file mode 100644
index 000000000..441676e7b
--- /dev/null
+++ b/tests/test-sigma/src/main/java/org/example/myapp/web/Hallo.java
@@ -0,0 +1,13 @@
+package org.example.myapp.web;
+
+import io.avaje.http.api.Controller;
+import io.avaje.http.api.Path;
+
+@Controller
+@Path("hallo")
+public class Hallo {
+
+ public String getStuff() {
+ return "Hallo";
+ }
+}
diff --git a/tests/test-sigma/src/main/java/org/example/myapp/web/HelloController.java b/tests/test-sigma/src/main/java/org/example/myapp/web/HelloController.java
new file mode 100644
index 000000000..6beaa9b3d
--- /dev/null
+++ b/tests/test-sigma/src/main/java/org/example/myapp/web/HelloController.java
@@ -0,0 +1,190 @@
+package org.example.myapp.web;
+
+import static java.util.Objects.requireNonNull;
+
+import java.time.LocalDate;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Executors;
+
+import org.example.myapp.service.MyService;
+import org.example.myapp.web.other.Foo;
+
+import io.avaje.http.api.BeanParam;
+import io.avaje.http.api.Controller;
+import io.avaje.http.api.Default;
+import io.avaje.http.api.Delete;
+import io.avaje.http.api.Form;
+import io.avaje.http.api.Get;
+import io.avaje.http.api.MediaType;
+import io.avaje.http.api.Path;
+import io.avaje.http.api.Post;
+import io.avaje.http.api.Produces;
+import io.avaje.http.api.QueryParam;
+import io.avaje.http.api.Valid;
+import io.avaje.sigma.HttpContext;
+import io.swagger.v3.oas.annotations.Hidden;
+import jakarta.inject.Inject;
+
+/**
+ * Hello resource manager.
+ *
+ * Simple API for Hello resources.
+ */
+//@Hidden
+@Valid
+@Controller
+@Path("/hello")
+class HelloController {
+
+ private final MyService myService;
+
+ @Inject
+ HelloController(MyService myService) {
+ this.myService = myService;
+ }
+
+ @Produces(MediaType.TEXT_PLAIN)
+ @Get("message")
+ String getPlainMessage() {
+ return "hello world";
+ }
+
+ /**
+ * Return the Hello DTO.
+ *
+ * @param id The hello Id.
+ * @param date The name of the hello
+ * @param otherParam Optional other parameter
+ * @return The Hello DTO given the id and name.
+ * @deprecated Please migrate away
+ */
+ @Deprecated
+ @Get("/:id/:date")
+ HelloDto hello(int id, LocalDate date, String otherParam) {
+ return new HelloDto(id, date.toString(), otherParam);
+ }
+
+ /**
+ * Find Hellos by name.
+ *
+ * @param name The name to search for
+ * @param myParam My option parameter
+ * @return The Hellos that we found.
+ */
+ @Get("/findbyname/{name}")
+ List findByName(String name, @QueryParam("my-param") @Default("one") String myParam) {
+ return new ArrayList<>();
+ }
+
+ /**
+ * Simple example post with JSON body response.
+ */
+ @Produces(MediaType.APPLICATION_JSON_PATCH_JSON)
+ @Post
+ HelloDto post(HelloDto dto) {
+ dto.name = "posted";
+ return dto;
+ }
+
+ /**
+ * Save the hello using json body.
+ *
+ * @param foo The hello doo id
+ * @param dto The hello body as json
+ */
+ @Post("/savebean/:foo")
+ void saveBean(String foo, HelloDto dto, HttpContext HttpContext) {
+ // save hello data ...
+ System.out.println("save " + foo + " dto:" + dto);
+ requireNonNull(foo);
+ requireNonNull(dto);
+ requireNonNull(HttpContext);
+ }
+
+ /**
+ * Create the new Hello using a form.
+ */
+ @Post("saveform")
+ @Form
+ void saveForm(HelloForm helloForm) {
+ System.out.println("saving " + helloForm);
+ }
+
+ @Form @Post("mySave")
+ void saveForm324(@Default("junk") String name, String email, String url) {
+ System.out.println("name " + name + " email:" + email + " url:" + url);
+ }
+
+
+ @Post("saveform2")
+ @Form
+ void saveForm2(String name, String email, String url) {
+ System.out.println("name " + name + " email:" + email + " url:" + url);
+ }
+
+ @Post("saveform3")
+ @Form
+ HelloDto saveForm3(HelloForm helloForm) {
+ return new HelloDto(52, helloForm.name, helloForm.email);
+ }
+
+ @Produces("text/plain")
+ @Get("withValidBean")
+ String getGetBeanForm(@BeanParam GetBeanForm bean) {
+ return "ok name:" + bean.getName();
+ }
+
+ @Hidden
+ @Get
+ List getAll() {
+ return myService.findAll();
+ }
+
+ @Get("/async")
+ CompletableFuture> getAllAsync() {
+ return CompletableFuture.supplyAsync(() -> {
+ // Simulate a delay as if an actual IO operation is being executed.
+ // This also helps ensure that we aren't just getting lucky with timings.
+ try {
+ Thread.sleep(10L);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+
+ return myService.findAll();
+ }, Executors.newSingleThreadExecutor()); // Example of how to use a custom executor.
+ }
+
+ // @Hidden
+ @Delete(":id")
+ void deleteById(int id) {
+ System.out.println("deleting " + id);
+ }
+
+ @Produces("text/plain")
+ @Get("/withMatrix/:year;author;country/:other")
+ String getWithMatrixParam(int year, String author, String country, String other, String extra) {
+ return "yr:" + year + " au:" + author + " co:" + country + " other:" + other + " extra:" + extra;
+ }
+
+ @Produces("text/plain")
+ @Get("slash/{name}//other/")
+ String slashAccepting(String name, String nam0, String nam1) {
+ return "got name:" + name + " splat0:" + nam0 + " splat1:" + nam1;
+ }
+
+ @Produces(value = "text/plain")
+ @Get("controlStatusCode")
+ String controlStatusCode(HttpContext ctx) {
+ ctx.status(201);
+ return "controlStatusCode";
+ }
+
+ @Produces(value = "text/plain")
+ @Get("takesNestedEnum")
+ String takesNestedEnum(Foo.NestedEnum myEnum) {
+ return "takesNestedEnum-" + myEnum;
+ }
+}
diff --git a/tests/test-sigma/src/main/java/org/example/myapp/web/HelloDto.java b/tests/test-sigma/src/main/java/org/example/myapp/web/HelloDto.java
new file mode 100644
index 000000000..ac3762420
--- /dev/null
+++ b/tests/test-sigma/src/main/java/org/example/myapp/web/HelloDto.java
@@ -0,0 +1,56 @@
+package org.example.myapp.web;
+
+import java.time.Instant;
+import java.util.UUID;
+
+import io.avaje.jsonb.Json;
+@Json
+public class HelloDto {
+
+ public int id;
+ /**
+ * This is a comment.
+ */
+ public String name;
+ /**
+ * This is a comment
+ */
+ public String otherParam;
+ private UUID gid;
+
+ private Instant whenAction;
+
+ public HelloDto(int id, String name, String otherParam) {
+ this.id = id;
+ this.name = name;
+ this.otherParam = otherParam;
+ }
+
+ /**
+ * Jackson constructor.
+ */
+ public HelloDto() {
+ }
+
+ public UUID getGid() {
+ return gid;
+ }
+
+ public void setGid(UUID gid) {
+ this.gid = gid;
+ }
+
+ public Instant getWhenAction() {
+ return whenAction;
+ }
+
+ public void setWhenAction(Instant whenAction) {
+ this.whenAction = whenAction;
+ }
+
+ @Override
+ public String toString() {
+ return "id:" + id + " name:" + name + " other:" + otherParam;
+ }
+
+}
diff --git a/tests/test-sigma/src/main/java/org/example/myapp/web/HelloForm.java b/tests/test-sigma/src/main/java/org/example/myapp/web/HelloForm.java
new file mode 100644
index 000000000..51dcfb085
--- /dev/null
+++ b/tests/test-sigma/src/main/java/org/example/myapp/web/HelloForm.java
@@ -0,0 +1,83 @@
+package org.example.myapp.web;
+
+import java.time.LocalDate;
+
+import org.hibernate.validator.constraints.URL;
+
+import io.avaje.jsonb.Json;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.Email;
+import jakarta.validation.constraints.Future;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Size;
+
+@Json
+@Valid
+public class HelloForm {
+
+ @NotNull
+ @Size(min = 2, max = 150)
+ String name;
+
+ @Email
+ @Size(max = 100)
+ String email;
+@URL
+ private String url;
+@Future
+ public LocalDate startDate;
+
+ public HelloForm(String name, String email) {
+ this.name = name;
+ this.email = email;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getEmail() {
+ return email;
+ }
+
+ public void setEmail(String email) {
+ this.email = email;
+ }
+
+ public String getUrl() {
+ return url;
+ }
+
+ public void setUrl(String url) {
+ this.url = url;
+ }
+
+ public LocalDate getStartDate() {
+ return startDate;
+ }
+
+ public void setStartDate(LocalDate startDate) {
+ this.startDate = startDate;
+ }
+
+ @Override
+ public String toString() {
+ return "HelloForm{"
+ + "name='"
+ + name
+ + '\''
+ + ", email='"
+ + email
+ + '\''
+ + ", url='"
+ + url
+ + '\''
+ + ", startDate="
+ + startDate
+ + '}';
+ }
+}
diff --git a/tests/test-sigma/src/main/java/org/example/myapp/web/Repository.java b/tests/test-sigma/src/main/java/org/example/myapp/web/Repository.java
new file mode 100644
index 000000000..de24d26ca
--- /dev/null
+++ b/tests/test-sigma/src/main/java/org/example/myapp/web/Repository.java
@@ -0,0 +1,13 @@
+package org.example.myapp.web;
+
+import java.util.List;
+
+public interface Repository {
+
+ T findById(I id);
+
+ List findAll();
+
+ I save(T bean);
+}
+
diff --git a/tests/test-sigma/src/main/java/org/example/myapp/web/SecurityController.java b/tests/test-sigma/src/main/java/org/example/myapp/web/SecurityController.java
new file mode 100644
index 000000000..4668a9b91
--- /dev/null
+++ b/tests/test-sigma/src/main/java/org/example/myapp/web/SecurityController.java
@@ -0,0 +1,22 @@
+package org.example.myapp.web;
+
+import io.avaje.http.api.Controller;
+import io.avaje.http.api.Get;
+import io.avaje.http.api.Path;
+import io.swagger.v3.oas.annotations.security.SecurityRequirement;
+
+@Controller
+@Path("/security")
+class SecurityController {
+
+ @Get("/first")
+ @SecurityRequirement(name = "JWT")
+ String first() {
+ return "simple";
+ }
+
+ @Get("/second")
+ String second() {
+ return "simple";
+ }
+}
diff --git a/tests/test-sigma/src/main/java/org/example/myapp/web/ServerType.java b/tests/test-sigma/src/main/java/org/example/myapp/web/ServerType.java
new file mode 100644
index 000000000..244f00545
--- /dev/null
+++ b/tests/test-sigma/src/main/java/org/example/myapp/web/ServerType.java
@@ -0,0 +1,7 @@
+package org.example.myapp.web;
+
+public enum ServerType {
+ PROXY,
+ HIDE_N_SEEK,
+ FFA
+}
diff --git a/tests/test-sigma/src/main/java/org/example/myapp/web/other/Foo.java b/tests/test-sigma/src/main/java/org/example/myapp/web/other/Foo.java
new file mode 100644
index 000000000..f3ed0507a
--- /dev/null
+++ b/tests/test-sigma/src/main/java/org/example/myapp/web/other/Foo.java
@@ -0,0 +1,7 @@
+package org.example.myapp.web.other;
+
+public class Foo {
+ public enum NestedEnum {
+ A, B, C
+ }
+}
diff --git a/tests/test-sigma/src/main/java/org/example/myapp/web/test/ErrorResponse.java b/tests/test-sigma/src/main/java/org/example/myapp/web/test/ErrorResponse.java
new file mode 100644
index 000000000..4611cc712
--- /dev/null
+++ b/tests/test-sigma/src/main/java/org/example/myapp/web/test/ErrorResponse.java
@@ -0,0 +1,7 @@
+package org.example.myapp.web.test;
+
+public class ErrorResponse {
+
+ public String id;
+ public String text;
+}
diff --git a/tests/test-sigma/src/main/java/org/example/myapp/web/test/HealthController.java b/tests/test-sigma/src/main/java/org/example/myapp/web/test/HealthController.java
new file mode 100644
index 000000000..8cdbea60a
--- /dev/null
+++ b/tests/test-sigma/src/main/java/org/example/myapp/web/test/HealthController.java
@@ -0,0 +1,30 @@
+package org.example.myapp.web.test;
+
+import io.avaje.http.api.Get;
+import io.avaje.http.api.MediaType;
+import io.avaje.http.api.OpenAPIResponse;
+import io.avaje.http.api.Path;
+import io.avaje.http.api.Produces;
+import io.swagger.v3.oas.annotations.OpenAPIDefinition;
+import io.swagger.v3.oas.annotations.info.Info;
+import io.swagger.v3.oas.annotations.tags.Tag;
+
+@Path("javalin")
+@OpenAPIDefinition(
+ info =
+ @Info(
+ title = "Example service showing off the Path extension method of controller",
+ description = ""))
+@OpenAPIResponse(responseCode = 403, description = "Not Authorized")
+public interface HealthController {
+ /**
+ * Standard Get
+ *
+ * @return a health check
+ */
+ @Get("/health")
+ @Produces(MediaType.TEXT_PLAIN)
+ @Tag(name = "tag1", description = "it's somethin")
+ @OpenAPIResponse(responseCode = 500, type = ErrorResponse.class)
+ String health();
+}
diff --git a/tests/test-sigma/src/main/java/org/example/myapp/web/test/HealthControllerImpl.java b/tests/test-sigma/src/main/java/org/example/myapp/web/test/HealthControllerImpl.java
new file mode 100644
index 000000000..e89195d97
--- /dev/null
+++ b/tests/test-sigma/src/main/java/org/example/myapp/web/test/HealthControllerImpl.java
@@ -0,0 +1,13 @@
+package org.example.myapp.web.test;
+
+import io.avaje.http.api.Controller;
+
+@Controller
+public class HealthControllerImpl implements HealthController {
+
+ @Override
+ public String health() {
+
+ return "this feels like a picnic *chew*";
+ }
+}
diff --git a/tests/test-sigma/src/main/java/org/example/myapp/web/test/MyForm.java b/tests/test-sigma/src/main/java/org/example/myapp/web/test/MyForm.java
new file mode 100644
index 000000000..8b7207843
--- /dev/null
+++ b/tests/test-sigma/src/main/java/org/example/myapp/web/test/MyForm.java
@@ -0,0 +1,8 @@
+package org.example.myapp.web.test;
+
+public class MyForm {
+
+ public String name;
+ public String email;
+ public String url;
+}
diff --git a/tests/test-sigma/src/main/java/org/example/myapp/web/test/OpenAPIController.java b/tests/test-sigma/src/main/java/org/example/myapp/web/test/OpenAPIController.java
new file mode 100644
index 000000000..39764584b
--- /dev/null
+++ b/tests/test-sigma/src/main/java/org/example/myapp/web/test/OpenAPIController.java
@@ -0,0 +1,102 @@
+package org.example.myapp.web.test;
+
+import java.util.List;
+
+import io.avaje.http.api.Controller;
+import io.avaje.http.api.Get;
+import io.avaje.http.api.MediaType;
+import io.avaje.http.api.OpenAPIResponse;
+import io.avaje.http.api.OpenAPIResponses;
+import io.avaje.http.api.Path;
+import io.avaje.http.api.Post;
+import io.avaje.http.api.Produces;
+import io.avaje.http.api.Put;
+import io.avaje.sigma.HttpContext;
+import io.swagger.v3.oas.annotations.OpenAPIDefinition;
+import io.swagger.v3.oas.annotations.enums.SecuritySchemeIn;
+import io.swagger.v3.oas.annotations.enums.SecuritySchemeType;
+import io.swagger.v3.oas.annotations.info.Info;
+import io.swagger.v3.oas.annotations.security.SecurityScheme;
+import io.swagger.v3.oas.annotations.tags.Tag;
+
+@OpenAPIDefinition(
+ info =
+ @Info(
+ title = "Example service",
+ description = "Example Javalin controllers with Java and Maven"))
+@Controller
+@Path("openapi/")
+@SecurityScheme(
+ type = SecuritySchemeType.APIKEY,
+ in = SecuritySchemeIn.QUERY,
+ name = "JWT",
+ paramName = "access_token",
+ description =
+ "JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties.")
+public class OpenAPIController {
+
+ /**
+ * Example of Open API Get (up to the first period is the summary). When using Javalin HttpContext
+ * only
+ * This Javadoc description is added to the generated openapi.json
+ *
+ * @return funny phrase (this part of the javadoc is added to the response desc)
+ */
+ @Get("/get")
+ @Produces(MediaType.TEXT_PLAIN)
+ @OpenAPIResponse(responseCode = 200, type = String.class)
+ void ctxEndpoint(HttpContext ctx) {
+ ctx.contentType(MediaType.TEXT_PLAIN).result("healthlmao");
+ }
+
+ /**
+ * Standard Post. uses tag annotation to add tags to openapi json
+ *
+ * @param b the body (this is used for generated request body desc)
+ * @return the response body (from javadoc)
+ */
+ @Post("/post")
+ @Tag(name = "tag1", description = "this is added to openapi tags")
+ @OpenAPIResponse(responseCode = 200, description = "overrides @return javadoc description")
+ @OpenAPIResponse(responseCode = 201)
+ @OpenAPIResponse(
+ responseCode = 400,
+ description = "User not found (Will not have an associated response schema)")
+ @OpenAPIResponse(
+ responseCode = 500,
+ description = "Some other Error (Will have this error class as the response class)",
+ type = ErrorResponse.class)
+ Person testPost(Person b) {
+ return new Person(0, "baby");
+ }
+
+ /**
+ * Standard Post. The Deprecated annotation adds "deprecacted:true" to the generated json
+ *
+ * @param m the body
+ * @return the response body (from javadoc)
+ */
+ @Deprecated
+ @Post("/post1")
+ @OpenAPIResponses({
+ @OpenAPIResponse(responseCode = 400, description = "User not found"),
+ @OpenAPIResponse(
+ responseCode = 500,
+ description = "Some other Error",
+ type = ErrorResponse.class)
+ })
+ Person testPostList(List m) {
+ return new Person(0, "baby");
+ }
+
+ @Put("/put")
+ @Produces(value = MediaType.TEXT_PLAIN, statusCode = 203)
+ @OpenAPIResponse(responseCode = 204, type = String.class)
+ String testDefaultStatus(HttpContext ctx) {
+ if (ctx.contentType().equals(MediaType.APPLICATION_PDF)) {
+ ctx.status(204);
+ return "";
+ }
+ return "only partial info";
+ }
+}
diff --git a/tests/test-sigma/src/main/java/org/example/myapp/web/test/Person.java b/tests/test-sigma/src/main/java/org/example/myapp/web/test/Person.java
new file mode 100644
index 000000000..434251ba0
--- /dev/null
+++ b/tests/test-sigma/src/main/java/org/example/myapp/web/test/Person.java
@@ -0,0 +1,31 @@
+package org.example.myapp.web.test;
+
+import io.avaje.jsonb.Json;
+
+@Json
+public class Person {
+
+ long id;
+ String name;
+
+ public Person(long id, String name) {
+ this.id = id;
+ this.name = name;
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+}
diff --git a/tests/test-sigma/src/main/java/org/example/myapp/web/test/TestController.java b/tests/test-sigma/src/main/java/org/example/myapp/web/test/TestController.java
new file mode 100644
index 000000000..036777241
--- /dev/null
+++ b/tests/test-sigma/src/main/java/org/example/myapp/web/test/TestController.java
@@ -0,0 +1,130 @@
+package org.example.myapp.web.test;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+
+import org.example.myapp.web.HelloDto;
+import org.example.myapp.web.ServerType;
+
+import io.avaje.http.api.Controller;
+import io.avaje.http.api.Default;
+import io.avaje.http.api.Form;
+import io.avaje.http.api.Get;
+import io.avaje.http.api.Header;
+import io.avaje.http.api.MatrixParam;
+import io.avaje.http.api.MediaType;
+import io.avaje.http.api.Path;
+import io.avaje.http.api.Post;
+import io.avaje.http.api.Produces;
+import io.avaje.http.api.Put;
+import io.avaje.http.api.QueryParam;
+import io.avaje.sigma.HttpContext;
+
+@Controller
+@Path("test/")
+public class TestController {
+
+ @Get
+ @Produces(MediaType.TEXT_PLAIN)
+ String basic() {
+ return "Hello world - index";
+ }
+
+ @Get("hey")
+ @Produces(MediaType.TEXT_PLAIN)
+ String helloWorld() {
+ return "Hello world";
+ }
+
+ @Get("/ctx")
+ void testVoid(HttpContext ctx) {
+ ctx.result("success path:" + ctx.path());
+ }
+
+ @Get("/header")
+ String testHeader(@Header String head) {
+ return head;
+ }
+
+ @Get("person/{name}")
+ Person testParamAndBody(String name) {
+ return new Person(42, name + " hello");
+ }
+
+ @Post("/person")
+ Person testPostPerson(Person body) {
+ return new Person(42, "Returning " + body.getName());
+ }
+
+ @Get("person/{sortBy}/list")
+ List testPersonList(String sortBy) {
+ return List.of(new Person(42, "fooList"), new Person(43, "barList"));
+ }
+
+ // curl -v localhost:8081/person/foo/set
+ @Get("person/{sortBy}/set")
+ Set testPersonSet(String sortBy) {
+ return Set.of(new Person(42, "fooSet"), new Person(43, "barSet"));
+ }
+
+ @Get("person/{sortBy}/map")
+ Map testPersonMap(String sortBy) {
+ return Map.of("one", new Person(42, "fooMap"), "two", new Person(43, "barMap"));
+ }
+
+ @Put("person/update")
+ String testPersonListBody(List newGuys) {
+ return "New Guys Added";
+ }
+
+ @Put("int")
+ int testIntReturn() {
+ return 422;
+ }
+
+ @Put("long")
+ long testLongReturn() {
+ return 69;
+ }
+
+ // curl -X POST http://localhost:8081/form
+ // -H "Content-Type: application/x-www-form-urlencoded"
+ // -d "name=Jimmy&email=jim@foo&url=notaurl"
+ @Form
+ @Post("form")
+ String testForm(String name, String email, String url) {
+ return name + "-" + email + "-" + url;
+ }
+
+ // curl -X POST http://localhost:8081/formBean
+ // -H "Content-Type:application/x-www-form-urlencoded"
+ // -d "name=FormBeanJimmy&email=jim@foo&url=notaurl"
+ @Form
+ @Post("formBean")
+ String testFormBean(MyForm form) {
+ return form.name + "|" + form.email + "|" + form.url;
+ }
+
+ @Get("/withMatrixParam/{type-1;category;vendor-34}/{range;style}")
+ void neo(
+ @MatrixParam("type-1") String type,
+ String category,
+ @MatrixParam("vendor-34") String vendor,
+ String range,
+ String style) {
+
+ System.out.println("Ever have that feeling where you're not sure if you're awake or dreaming?");
+ }
+
+ @Get("/async")
+ CompletableFuture getAllAsync() {
+ return CompletableFuture.supplyAsync(() -> new HelloDto(12, "Jim", "asd"));
+ }
+
+ @Get("/enumQuery2")
+ String enumMultiQuery(@QueryParam @Default({"FFA", "PROXY"}) Set type) {
+ return type.toString();
+ }
+}
diff --git a/tests/test-sigma/src/main/java/org/example/myapp/web/test/TestController2.java b/tests/test-sigma/src/main/java/org/example/myapp/web/test/TestController2.java
new file mode 100644
index 000000000..b4b20804b
--- /dev/null
+++ b/tests/test-sigma/src/main/java/org/example/myapp/web/test/TestController2.java
@@ -0,0 +1,95 @@
+package org.example.myapp.web.test;
+
+import java.util.Set;
+
+import org.example.myapp.web.ServerType;
+
+import io.avaje.http.api.BodyString;
+import io.avaje.http.api.Controller;
+import io.avaje.http.api.Default;
+import io.avaje.http.api.ExceptionHandler;
+import io.avaje.http.api.Filter;
+import io.avaje.http.api.Form;
+import io.avaje.http.api.FormParam;
+import io.avaje.http.api.Get;
+import io.avaje.http.api.InstrumentServerContext;
+import io.avaje.http.api.Path;
+import io.avaje.http.api.Post;
+import io.avaje.http.api.QueryParam;
+import io.avaje.sigma.HttpContext;
+
+@Path("test/")
+@Controller
+public class TestController2 {
+
+ @Form
+ @Get("/enumForm")
+ @InstrumentServerContext
+ void enumForm(String s, ServerType type, HttpContext ctx) {
+ ctx.result(s);
+ }
+
+ @Get("/enumFormParam")
+ @InstrumentServerContext
+ String enumFormParam(@FormParam String s, @FormParam ServerType type) throws Exception {
+ return type.name();
+ }
+
+ @Get("/enumQuery")
+ String enumQuery(@QueryParam @Default("FFA") ServerType type) {
+ return type.name();
+ }
+
+ @Post("/enumQueryImplied")
+ String enumQueryImplied(String s, @QueryParam ServerType type) {
+ return type.name();
+ }
+
+ @Post("/enumPath/{type}")
+ String enumPath(ServerType type) {
+ return type.name();
+ }
+
+ @Post("/strBody")
+ @InstrumentServerContext
+ String strBody(@BodyString String body) {
+ return body;
+ }
+
+ @ExceptionHandler
+ String exception(Exception ex) {
+
+ return "";
+ }
+
+ @ExceptionHandler
+ String exceptionCtx(Exception ex, HttpContext ctx) {
+
+ return "";
+ }
+
+ @ExceptionHandler(RuntimeException.class)
+ void exceptionVoid(HttpContext ctx) {
+ System.err.println("do nothing lmao");
+ }
+
+ // @After
+ void after(String s, ServerType type, HttpContext ctx) {
+ ctx.result(s);
+ }
+
+ // @Before
+ void before(String s, ServerType type, HttpContext ctx) {
+ ctx.result(s);
+ }
+
+ @Filter
+ void filter(HttpContext ctx) {
+ }
+
+ @Form
+ @Get("/formMulti")
+ String formMulti(Set strings) {
+ return strings.toString();
+ }
+}
diff --git a/tests/test-sigma/src/main/resources/logback.xml b/tests/test-sigma/src/main/resources/logback.xml
new file mode 100644
index 000000000..1119a0c85
--- /dev/null
+++ b/tests/test-sigma/src/main/resources/logback.xml
@@ -0,0 +1,18 @@
+
+
+
+ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/test-sigma/src/test/java/io/avaje/http/generator/SigmaProcessorTest.java b/tests/test-sigma/src/test/java/io/avaje/http/generator/SigmaProcessorTest.java
new file mode 100644
index 000000000..dda2e39b7
--- /dev/null
+++ b/tests/test-sigma/src/test/java/io/avaje/http/generator/SigmaProcessorTest.java
@@ -0,0 +1,102 @@
+package io.avaje.http.generator;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Set;
+
+import javax.tools.JavaFileObject;
+import javax.tools.JavaFileObject.Kind;
+import javax.tools.StandardLocation;
+import javax.tools.ToolProvider;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Test;
+
+import io.avaje.http.generator.sigma.SigmaProcessor;
+import io.avaje.jsonb.generator.JsonbProcessor;
+
+class SigmaProcessorTest {
+
+ @AfterEach
+ void deleteGeneratedFiles() throws IOException {
+
+ Paths.get("openapi.json").toAbsolutePath().toFile().delete();
+
+ Files.walk(Paths.get("org").toAbsolutePath())
+ .sorted(Comparator.reverseOrder())
+ .map(Path::toFile)
+ .forEach(File::delete);
+ }
+
+ @Test
+ public void runAnnotationProcessor() throws Exception {
+ final var source = Paths.get("src").toAbsolutePath().toString();
+
+ final var files = getSourceFiles(source);
+
+ final var compiler = ToolProvider.getSystemJavaCompiler();
+
+ final var task =
+ compiler.getTask(
+ new PrintWriter(System.out),
+ null,
+ null,
+ List.of("--release=11", "-AdisableDirectWrites=true"),
+ null,
+ files);
+ task.setProcessors(List.of(new SigmaProcessor()));
+
+ assertThat(task.call()).isTrue();
+ assert Files.readString(
+ Paths.get("org/example/myapp/web/BarController$Route.java").toAbsolutePath())
+ .contains("io.avaje.inject.Component");
+ }
+
+ @Test
+ void runAnnotationProcessorJakarta() throws Exception {
+ final var source = Paths.get("src").toAbsolutePath().toString();
+
+ final var files = getSourceFiles(source);
+
+ final var compiler = ToolProvider.getSystemJavaCompiler();
+
+ final var task =
+ compiler.getTask(
+ new PrintWriter(System.out),
+ null,
+ null,
+ List.of(
+ "--release=11",
+ "-AuseJavax=false",
+ "-AuseSingleton=true",
+ "-AdisableDirectWrites=true"),
+ null,
+ files);
+ task.setProcessors(List.of(new SigmaProcessor(), new JsonbProcessor()));
+
+ assertThat(task.call()).isTrue();
+
+ assert Files.readString(
+ Paths.get("org/example/myapp/web/BarController$Route.java").toAbsolutePath())
+ .contains("jakarta.inject.Singleton");
+ }
+
+ private Iterable getSourceFiles(String source) throws Exception {
+ final var compiler = ToolProvider.getSystemJavaCompiler();
+ final var files = compiler.getStandardFileManager(null, null, null);
+
+ files.setLocation(StandardLocation.SOURCE_PATH, List.of(new File(source)));
+
+ final Set fileKinds = Collections.singleton(Kind.SOURCE);
+ return files.list(StandardLocation.SOURCE_PATH, "", fileKinds, true);
+ }
+}
diff --git a/tests/test-sigma/src/test/resources/application-test.yaml b/tests/test-sigma/src/test/resources/application-test.yaml
new file mode 100644
index 000000000..ae43f3a1f
--- /dev/null
+++ b/tests/test-sigma/src/test/resources/application-test.yaml
@@ -0,0 +1,6 @@
+ebean:
+ test:
+# shutdown: remove # stop | remove
+ platform: h2 # h2, postgres, mysql, mariadb, sqlserver, oracle, hana, clickhouse, sqlite
+ ddlMode: dropCreate # none | dropCreate | create | migration | createOnly | migrationDropCreate
+ dbName: my_app
diff --git a/tests/test-sigma/src/test/resources/logback-test.xml b/tests/test-sigma/src/test/resources/logback-test.xml
new file mode 100644
index 000000000..8467abcc9
--- /dev/null
+++ b/tests/test-sigma/src/test/resources/logback-test.xml
@@ -0,0 +1,19 @@
+
+
+
+ TRACE
+
+
+ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
+
+
+
+
+
+
+
+
+
+
+
+