### Context-Less Persistence Service with Transaction Management Source: https://github.com/yupiik/fusion/blob/master/fusion-documentation/src/main/minisite/content/fusion/persistence.adoc Illustrates a typical setup for a persisting service using `ContextLessDatabase` and `TransactionManager`. This example shows how to inject dependencies and perform context-less write operations within a transaction. ```java @ApplicationScoped public class MyPersistingService { private final TransactionManager txMgr; private final ContextLessDatabase db; // constructor to get injections public void insert(final MyModel model) { txMgr.write(connection -> db.insert(connection, model)); } } ``` -------------------------------- ### Start Fusion Container Source: https://github.com/yupiik/fusion/blob/master/fusion-documentation/src/main/minisite/content/fusion/examples.adoc Start the Fusion runtime container in two phases: configuration and launch. This provides a managed environment for your application's beans. ```java try ( final var container = ConfiguringContainer .of() <1> .start() <2> ) { // use the container or just await for the end of the application } ``` -------------------------------- ### Configuration for ConfigurationDocumentationGenerator Source: https://github.com/yupiik/fusion/blob/master/fusion-documentation/src/main/minisite/content/fusion/documentation.adoc Example configuration for the ConfigurationDocumentationGenerator when used with Yupiik minisite. This task formats configuration documentation in Asciidoc. ```xml io.yupiik.fusion.documentation.ConfigurationDocumentationGenerator ``` -------------------------------- ### Implement BEFORE Task with Supplier Source: https://github.com/yupiik/fusion/blob/master/fusion-documentation/src/main/minisite/content/fusion/testing.adoc Example of a BEFORE task implementing Task.Supplier. This task uses a Java Supplier to provide data, suitable for injecting state as parameters. ```java @DefaultScoped public class BeforeTask implements Task.Supplier { private final MyService service; // constructor... @Override public MyData get() { return service.createData(); } } ``` -------------------------------- ### Declarative Interceptor Example Source: https://github.com/yupiik/fusion/blob/master/fusion-documentation/src/main/minisite/content/fusion/index.adoc Illustrates a traditional declarative interceptor using an annotation. This approach is not supported by Fusion. ```java public class MyBean { @Traced public void doSomething() { // ... } } ``` -------------------------------- ### Custom JUnit 5 Extension for Configuration Source: https://github.com/yupiik/fusion/blob/master/fusion-documentation/src/main/minisite/content/fusion/testing.adoc Shows how to create a custom JUnit 5 extension to configure the Fusion container before it starts. This is useful for setting system properties or global services. ```java @Target(TYPE) @Retention(RUNTIME) @MonoFusionSupport @ExtendsWith(MyAppSupport.MyConf.class) public @interface MyAppSupport { class MyConf implements Extension { static { // do the configuration System.setProperty("....", "...."); } } } ``` -------------------------------- ### Configuration for CliDocumentationGenerator Source: https://github.com/yupiik/fusion/blob/master/fusion-documentation/src/main/minisite/content/fusion/documentation.adoc Example configuration for the CliDocumentationGenerator when used with Yupiik minisite. This task generates Asciidoc documentation for CLI modules. ```xml io.yupiik.fusion.documentation.CliDocumentationGenerator ``` -------------------------------- ### Java Main Class for Fusion Application Source: https://github.com/yupiik/fusion/blob/master/fusion-documentation/src/main/minisite/content/fusion/graalvm.adoc Example of a main class in a Fusion application that can be converted to a native binary. Ensure your dependencies are GraalVM compatible. ```java package demo.fusion; import io.yupiik.fusion.framework.api.ConfiguringContainer; import io.yupiik.fusion.framework.api.lifecycle.Start; import io.yupiik.fusion.framework.api.scope.ApplicationScoped; import io.yupiik.fusion.framework.build.api.event.OnEvent; import io.yupiik.fusion.framework.build.api.lifecycle.Init; @ApplicationScoped public class Greeter { @Init protected void init() { System.out.println("> Init"); } public void onStart(@OnEvent final Start start) { System.out.println("> start: " + start); } public static void main(final String... args) { try (final var container = ConfiguringContainer.of().start()) { // no-op } } } ``` -------------------------------- ### Implement a Monitoring Endpoint Source: https://github.com/yupiik/fusion/blob/master/fusion-documentation/src/main/minisite/content/fusion/http-server.adoc Create a MonitoringEndpoint for health checks or metrics. This example checks transaction manager validity and returns metrics or an OK status. ```java @DefaultScoped public class Health implements MonitoringEndpoint { private final TransactionManager transactionManager; public Health(final TransactionManager transactionManager) { this.transactionManager = transactionManager; } @Override public boolean matches(final Request request) { return "GET".equalsIgnoreCase(request.method()) && "/metrics".equalsIgnoreCase(request.path()); } @Override public CompletionStage unsafeHandle(final Request request) { return transactionManager .read(c -> { try { if (!c.isValid(30_000)) { return Optional.of(fail("Timeout")); } return Optional.>empty(); } catch (final SQLException e) { return Optional.of(fail(e.getMessage())); } }) .orElseGet(() -> completedStage(Response.of().body("OK").build())); } } ``` -------------------------------- ### Testing a Launcher Application with @FusionCLITest Source: https://github.com/yupiik/fusion/blob/master/fusion-documentation/src/main/minisite/content/fusion/testing.adoc Example of using @FusionCLITest to test CLI applications. It automatically executes a Launcher with specified arguments and provides Stdout and Stderr for output validation. ```java @FusionCLITest(args = {"test", "run"}) void run(final Stdout stdout) { assertEquals("...", stdout.content().strip()); } ``` -------------------------------- ### Custom Resource Definition Example (YAML) Source: https://github.com/yupiik/fusion/blob/master/fusion-documentation/src/main/minisite/content/fusion/kubernetes-operator.adoc An example of a custom resource definition (CRD) for an API kind. Operators use these descriptors to manage custom resources. ```yaml apiVersion: custom.company.com/v1 kind: MyAPI metadata: name: my-api namespace: my-apps spec: path: /api/my image: company/my-api:1.0 ``` -------------------------------- ### Implement AFTER Task with Runnable Source: https://github.com/yupiik/fusion/blob/master/fusion-documentation/src/main/minisite/content/fusion/testing.adoc Example of an AFTER task implementing Task.Supplier. This task uses a Runnable to perform actions, typically for cleanup operations after a process. ```java @DefaultScoped public class AfterTask implements Task.Supplier { private final MyService service; // constructor... @Override public void run() { service.clean(); } } ``` -------------------------------- ### Kubernetes Operator Manifest Configuration Source: https://github.com/yupiik/fusion/blob/master/fusion-documentation/src/main/minisite/content/fusion/kubernetes-operator.adoc Example manifest.json file for configuring Kubernetes Operator deployments, including CRD-only, CRD controller, and full-stack alveoli. ```json { "$schema": "https://raw.githubusercontent.com/yupiik/bundlebee/gh-pages/generated/jsonschema/manifest.descriptor.json", "interpolateAlveoli": true, "alveoli": [ { "//": "CRD only, no controller", "name": "api-crd-only", "descriptors": [ { "name": "crd.json", "await": true, "awaitConditions": [ { "command": "apply", "conditions": [ { "type": "STATUS_CONDITION", "conditionType": "Established", "value": "True" } ] } ] } ] }, { "//": "CRD controller only registration", "name": "api-crd-controller", "descriptors": [ { "name": "serviceaccount.json" }, { "name": "role.json" }, { "name": "rolebinding.json" }, { "name": "deployment.json" } ] }, { "//": "full stack alveolus", "name": "api-crd", "dependencies": [ { "name": "api-crd-only" }, { "name": "api-crd-controller" } ] } ] } ``` -------------------------------- ### Configure ExtendedHttpClientConfiguration Source: https://github.com/yupiik/fusion/blob/master/fusion-documentation/src/main/minisite/content/fusion/http-client.adoc Configure the ExtendedHttpClientConfiguration with a custom SSL context and request listeners. This example shows how to set a custom HttpClient delegate and add listeners for timeouts, user agents, and exchange logging. ```java final var conf = new ExtendedHttpClientConfiguration(); // (optional) force a custom SSL context conf.setDelegate( HttpClient.newBuilder() .sslContext(getSSLContext()) .build()); // (optional) force custom listeners conf.setListeners(List.of( new AutoTimeoutSetter(Duration.ofSeconds(3600)), new AutoUserAgentSetter(), new ExchangeLogger( Logger.getLogger(getClass().getName()), Clock.systemUTC(), false))); ``` -------------------------------- ### Registering JsonConfigurationSource with @Bean Source: https://github.com/yupiik/fusion/blob/master/fusion-documentation/src/main/minisite/content/fusion/json.adoc Provides an example of registering a JsonConfigurationSource using a @Bean method. Note the warning about potential singleton cache issues. ```java public class MyListener { public void onStart(@OnEvent final ConfigurationRegistration event) { event.addSource().accept(new JsonConfigurationSource( ReaderSupplier.from( event.configuration().get("my.config.path").orElse("config.json"), "{\"myDefaultPort\": 8080}"))); } } ``` -------------------------------- ### Advanced Maven Configuration for IDE Completion Source: https://github.com/yupiik/fusion/blob/master/fusion-documentation/src/main/minisite/content/fusion/setup.adoc Configures Maven dependencies and the compiler plugin to avoid exposing the processor in IDE completion, suitable for complex setups. ```xml io.yupiik.fusion fusion-api ${fusion.version} io.yupiik.fusion fusion-build-api ${fusion.version} provided org.apache.maven.plugins maven-compiler-plugin 3.10.1 io.yupiik.fusion fusion-processor ${fusion.version} ``` -------------------------------- ### Entity Delete Hook Source: https://github.com/yupiik/fusion/blob/master/fusion-documentation/src/main/minisite/content/fusion/persistence.adoc Implement the @OnDelete hook to perform actions before an entity is deleted from the database. This example is a no-operation. ```java @OnDelete private void onDelete() { // no-op } ``` -------------------------------- ### Yupiik Fusion Core Dependencies for Maven Source: https://github.com/yupiik/fusion/blob/master/README.adoc Add these core dependencies to your Maven project to start using Yupiik Fusion. The scope for build-api and processor is provided. ```xml io.yupiik.fusion fusion-build-api ${fusion.version} provided io.yupiik.fusion fusion-processor ${fusion.version} provided io.yupiik.fusion fusion-api ${fusion.version} ``` -------------------------------- ### Custom Operator Implementation (Java) Source: https://github.com/yupiik/fusion/blob/master/fusion-documentation/src/main/minisite/content/fusion/kubernetes-operator.adoc An example of a custom operator extending `Operator.Base`. It demonstrates injecting Kubernetes client and JsonMapper, defining the custom resource model, and handling CRD events (add, delete, modify). ```java @ApplicationScoped public class APIOperator extends Operator.Base { // <1> private final Logger logger = Logger.getLogger(getClass().getName()); private final KubernetesClient kubernetes; private final JsonMapper jsonMapper; public APIOperator( // <2> final KubernetesClient client, final JsonMapper jsonMapper) { super( APIResource.class, // <3> // <4> new DefaultOperatorConfiguration(true, List.of("default"), "api", "company.com/v1")); this.kubernetes = client; this.jsonMapper = jsonMapper; } @Override public CompletionStage onStart() { // <5> logger.info(() -> "Starting operator " + getClass().getName()); return super.onStart(); } @Override // <6> public void onAdd(final APIResource object) { logger.info(() -> "[ADD] " + object); } @Override // <6> public void onDelete(final APIResource object) { logger.info(() -> "[DELETE] " + object); } @Override // <6> public void onModify(final APIResource object) { logger.info(() -> "[MODIFY] " + object); } } ``` -------------------------------- ### Maven Shade Plugin Configuration for Fusion Source: https://github.com/yupiik/fusion/blob/master/fusion-documentation/src/main/minisite/content/fusion/examples.adoc Configure the Maven Shade Plugin to create a fat JAR with custom transformers for Fusion applications. This setup includes transformers for manifest, services, documentation, JSON schema, and OpenRPC. ```xml org.apache.maven.plugins maven-shade-plugin 3.5.2 io.yupiik.maven maven-shade-transformers 0.0.5 shade true fat false ${project.build.directory}/reduced-pom.xml io.yupiik.fusion.framework.api.main.Launcher *:* module-info.class META-INF/*.SF META-INF/*.DSA META-INF/*.RSA META-INF/LICENSE.txt META-INF/LICENSE META-INF/NOTICE.txt META-INF/NOTICE META-INF/MANIFEST.MF META-INF/DEPENDENCIES ``` -------------------------------- ### Efficient Functional Interception with Parameters Source: https://github.com/yupiik/fusion/blob/master/fusion-documentation/src/main/minisite/content/fusion/index.adoc Provides an example of functional interception that efficiently handles parameters without creating Object arrays, suitable for scenarios like transaction management. ```java public class MyBean { @Injection EntityManager em; // assume the application used JPA - not required @Injection JpaService jpa; // custom bean to handle transactions for ex public void store(final Transaction tx) { tracing( // no Object[] created for an interceptor // and no reflection to extract the id tx.id(), () -> jpa.tx(() -> em.persist(tx))); } } ``` -------------------------------- ### Example API Custom Resource Definition (CRD) Source: https://github.com/yupiik/fusion/blob/master/fusion-documentation/src/main/minisite/content/fusion/kubernetes-operator.adoc Define the Custom Resource Definition (CRD) for your operator. This YAML file specifies the API group, versions, schema, and additional printer columns for your custom resource. ```json { "apiVersion": "apiextensions.k8s.io/v1", "kind": "CustomResourceDefinition", "metadata": { "name": "apis.company.com" }, "spec": { "group": "company.com", "versions": [ { "name": "v1", "served": true, "storage": true, "schema": { "openAPIV3Schema": { "type": "object", "properties": { "spec": { "type": "object", "properties": { "image": { "type": "string" }, "path": { "type": "string" } } } } } }, "additionalPrinterColumns": [ { "name": "Path", "type": "string", "description": "Path of the endpoint", "jsonPath": ".spec.path" }, { "name": "Image", "type": "string", "description": "Image of the main container containing the API", "jsonPath": ".spec.image" }, { "name": "Age", "type": "date", "jsonPath": ".metadata.creationTimestamp" } ] } ], "scope": "Namespaced", "names": { "plural": "apis", "singular": "api", "kind": "API" } } } ``` -------------------------------- ### Setting Application Configuration via Environment Variables (Bash) Source: https://github.com/yupiik/fusion/blob/master/fusion-documentation/src/main/minisite/content/fusion/examples.adoc Demonstrates how to set the complex `AppConfig` using environment variables in a bash script. This includes setting values for lists and maps. ```bash export APP_NAME="app1" export APP_HOST="app-1" export APP_PORT="8380" export APP_FREQUENCY_INTERVAL="20000L" export APP_SOURCES_LENGTH="2" export APP_SOURCES_0_HOST="external-host-1" export APP_SOURCES_0_PORT="8080" export APP_SOURCES_1_HOST="external-host-2" export APP_SOURCES_1_PORT="8080" export APP_STAMPS="application,server,integration" export APP_TAGS=" application = app1 env = local phase = tests " ``` -------------------------------- ### Setting Application Configuration via System Properties (Java) Source: https://github.com/yupiik/fusion/blob/master/fusion-documentation/src/main/minisite/content/fusion/examples.adoc Illustrates how to set the complex `AppConfig` by programmatically setting Java system properties. This is useful for configuring applications within a Java environment. ```java public class App{ static { System.setProperty("app.name", "app1"); System.setProperty("app.host", "app-1"); System.setProperty("app.port", "8380"); System.setProperty("app.frequency.interval", "20000l"); System.setProperty("app.sources.length", "2"); System.setProperty("app.sources.0.host", "ext"); System.setProperty("app.sources.0.port", "808"); System.setProperty("app.sources.1.host", "ext"); System.setProperty("app.sources.1.port", "808"); System.setProperty("app.stamps", "application,server,integration"); System.setProperty("app.tags"," \napplication = app1 \nenv = local \nphase = tests" ); } } ``` -------------------------------- ### Context-Less Database Insert Source: https://github.com/yupiik/fusion/blob/master/fusion-documentation/src/main/minisite/content/fusion/persistence.adoc Demonstrates how to perform a database insert using `ContextLessDatabase` by explicitly managing the connection. This approach avoids `ThreadLocal` dependencies. ```java try (final var connection = dataSource.getConnection()) { database.insert(connection, entity); } ``` -------------------------------- ### Executing Custom SQL Queries Source: https://github.com/yupiik/fusion/blob/master/fusion-documentation/src/main/minisite/content/fusion/persistence.adoc Demonstrates how to execute custom SQL queries using the database entity model. This allows for dynamic SQL generation based on entity metadata. ```java import io.yupiik.fusion.persistence.api.Database; import io.yupiik.fusion.persistence.api.Entity; import java.util.List; // Assuming Customer.class and CustomerEntity.class are defined elsewhere // final var database = ...; final var customer = database.entity(Customer.class); final var sql = "SELECT " + String.join(", ", customer.concatenateColumns(new Entity.ColumnsConcatenationRequest())) + "FROM " + customer.getTable() + "WHERE name = ?"; final var lines = database.query(Customer.class, sql, b -> b.bind("the-name")); ``` -------------------------------- ### Entity Update Hook Source: https://github.com/yupiik/fusion/blob/master/fusion-documentation/src/main/minisite/content/fusion/persistence.adoc Implement the @OnUpdate hook to perform actions before an entity is updated in the database. This example simply returns the current entity. ```java @OnUpdate private CustomerEntity onUpdate() { return this; } ``` -------------------------------- ### Setting Application Configuration via Environment Variables (YAML) Source: https://github.com/yupiik/fusion/blob/master/fusion-documentation/src/main/minisite/content/fusion/examples.adoc Shows how to set the complex `AppConfig` using environment variables in YAML format. This is an alternative to bash scripting for environment variable configuration. ```yaml APP_NAME: "app1" APP_HOST: "app-1" APP_PORT: "8380" APP_FREQUENCY_INTERVAL: "20000L" APP_SOURCES_LENGTH: "2" APP_SOURCES_0_HOST: "external-host-1" APP_SOURCES_0_PORT: "8080" APP_SOURCES_1_HOST: "external-host-2" APP_SOURCES_1_PORT: "8080" APP_STAMPS: "application,server,integration" APP_TAGS: | application = app1 env = local phase = tests ``` -------------------------------- ### Using TestClient for JSON-RPC Requests Source: https://github.com/yupiik/fusion/blob/master/fusion-documentation/src/main/minisite/content/fusion/testing.adoc Demonstrates how to use the TestClient utility to make JSON-RPC requests. It simplifies HTTP client interactions, logging, and exception handling in tests. ```java @Test void myTest(@Fusion final TestClient client) { final var res = client.jsonRpcRequest( "my.jsonrpc.method", Map.of("id", id.value())); final var order = res .asJsonRpc() .success() .as(Order.class); assertAll( () -> assertEquals(200, res.statusCode()), () -> assertInsertedOrder(order, id, res::body)); } ``` -------------------------------- ### HTTP Server Endpoints with Java Source: https://github.com/yupiik/fusion/blob/master/README.adoc Defines RESTful endpoints for product retrieval and order creation using annotations. Requires `io.yupiik.fusion.framework.api.scope.ApplicationScoped` and `io.yupiik.fusion.framework.build.api.http.HttpMatcher`. ```java import io.yupiik.fusion.framework.api.scope.ApplicationScoped; import io.yupiik.fusion.framework.build.api.http.HttpMatcher; import io.yupiik.fusion.http.server.api.HttpException; import io.yupiik.fusion.http.server.api.Request; import io.yupiik.fusion.http.server.api.Response; import io.yupiik.fusion.json.JsonMapper; @ApplicationScoped public class ProductEndpoint { private final ProductService productService; private final JsonMapper jsonMapper; public ProductEndpoint(final JsonMapper jsonMapper, final ProductService productService) { this.jsonMapper = jsonMapper; this.productService = productService; } @HttpMatcher(methods = "GET", path = "/product", pathMatching = HttpMatcher.PathMatching.EXACT) public List findAllProduct(final Request request) { return productService.findProducts(); } @HttpMatcher(methods = "GET", path = "/product/", pathMatching = HttpMatcher.PathMatching.STARTS_WITH) public Product findProduct(final Request request) { final var id = request.path().split("/")[2]; return productService.findProduct(id); } @HttpMatcher(methods = "POST", path = "/order", pathMatching = HttpMatcher.PathMatching.EXACT) public Response createOrder(final Request request, final Order order) { // custom response crafting return Response.of() .status(201) .header("content-type", "application/json") .body(jsonMapper.toString(orderService.createOrder(order))) .build(); } } ``` -------------------------------- ### Validate JSON with Json Schema Source: https://github.com/yupiik/fusion/blob/master/fusion-documentation/src/main/minisite/content/fusion/json.adoc Use the Json Schema Validator to validate JSON content against a JSON schema. This example shows a service with an injected JsonMapper. ```java @Bean public class MyService { @Injection JsonMapper mapper; ``` -------------------------------- ### Basic Fusion Test Class Source: https://github.com/yupiik/fusion/blob/master/fusion-documentation/src/main/minisite/content/fusion/testing.adoc Demonstrates how to use @FusionSupport to inject services into a test class. Requires a Fusion support annotation on the test class. ```java @FusionSupport class Mytest { @Test void run(@Fusion final MyService service) { // ... } } ``` -------------------------------- ### Create JsonConfigurationSource from File Source: https://github.com/yupiik/fusion/blob/master/fusion-documentation/src/main/minisite/content/fusion/json.adoc Initializes a JsonConfigurationSource to read configuration from a JSON file on the filesystem. Uses ReaderSupplier for file path resolution. ```java import io.yupiik.fusion.framework.api.io.ReaderSupplier; import io.yupiik.fusion.json.configuration.JsonConfigurationSource; // from a file final var source = new JsonConfigurationSource( ReaderSupplier.fromFile(Path.of("/etc/app/config.json"))); ``` -------------------------------- ### Read/Write JSON Data with JsonMapper Source: https://github.com/yupiik/fusion/blob/master/fusion-documentation/src/main/minisite/content/fusion/json.adoc Inject and use the JsonMapper to serialize Java objects to JSON and deserialize JSON to Java objects. This example shows writing data to an HttpServletResponse. ```java @Bean public class MyService extends HttpServlet { @Injection JsonMapper mapper; @Override public void doGet(final HttpServletRequest req, final HttpServletResponse resp) throws IOException { try (final var out = resp.getWriter()) { mapper.write(createMyModelInstance(req), out); } } } ``` -------------------------------- ### Injecting Server Configuration Source: https://github.com/yupiik/fusion/blob/master/fusion-documentation/src/main/minisite/content/fusion/examples.adoc Shows how to inject the `ServerConfiguration` record into a Spring bean. The configuration values are automatically bound. ```java @Bean public class MyServer { private final ServerConfiguration conf; public MyServer(final ServerConfiguration conf) { this.conf = conf; } // ... } ``` -------------------------------- ### Context-Less Database Write Operation Source: https://github.com/yupiik/fusion/blob/master/fusion-documentation/src/main/minisite/content/fusion/persistence.adoc Shows how to perform a write operation with `ContextLessDatabase` using a connection provider wrapper. This pattern is useful for encapsulating multiple database operations within a single transaction. ```java dataSource.write(connection -> { database.insert(connection, entity); aServiceDoingAnInsert(connection); }); ``` -------------------------------- ### JSON Map Support with $asList Source: https://github.com/yupiik/fusion/blob/master/fusion-documentation/src/main/minisite/content/fusion/json.adoc Shows how to represent a JSON object as a Map by setting '$asList': true. This allows accessing map entries by index. ```java final var source = new JsonConfigurationSource(mapper, () -> new StringReader("{\"config\": {\"$asList\": true,\"key1\": {\"enabled\": true},\"key2\": {\"enabled\": false}}}")); source.get("config.length"); // "2" source.get("config.0.key"); // "key1" source.get("config.0.value.enabled"); // "true" source.get("config.1.key"); // "key2" source.get("config.1.value.enabled"); // "false" ``` -------------------------------- ### Define a Greeting Endpoint Source: https://github.com/yupiik/fusion/blob/master/fusion-documentation/src/main/minisite/content/fusion/http-server.adoc Implement the Endpoint interface to create a custom web service endpoint. The matches method determines if the endpoint should handle the request, and the handle method provides the response. ```java @Bean public class Greeting implements Endpoint { @Override public boolean matches(final Request request) { return "GET".equals(request.method()); } @Override public CompletionStage handle(final Request request) { return completedFuture(Response.of() .body("{\"hello\":true}") .build()); } } ``` -------------------------------- ### Configure Kubernetes Client with Extended HTTP Client Source: https://github.com/yupiik/fusion/blob/master/fusion-documentation/src/main/minisite/content/fusion/http-client.adoc Configure the Kubernetes client to use an extended HTTP client by setting a client wrapper. This approach avoids manual SSLContext handling. ```java final var conf = new KubernetesClientConfiguration() .setClientWrapper(client -> new ExtendedHttpClient(new ExtendedHttpClientConfiguration() .setDelegate(client))); final var k8s = new KubernetesClient(conf); // now call any API you need: final var response = k8s.send( HttpRequest.newBuilder() .GET() .uri(URI.create( "https://kubernetes.api/api/v1/namespaces/" + k8s.namespace().orElse("default") + "/configmaps?" + "includeUninitialized=false&" + "limit=1000&" + "timeoutSeconds=600") .header("Accept", "application/json") .build(), HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8))); // handle the response ``` -------------------------------- ### Advanced Queries with Virtual Tables and Joins Source: https://github.com/yupiik/fusion/blob/master/fusion-documentation/src/main/minisite/content/fusion/persistence.adoc Shows how to perform advanced queries involving joins between entities using virtual tables. It demonstrates constructing complex SQL and mapping results to a specific model. ```java import io.yupiik.fusion.persistence.api.Database; import io.yupiik.fusion.persistence.api.Entity; import java.util.List; import java.util.Set; import java.util.stream.Collectors; // Assuming Entity1.class, Entity2.class, JoinModel.class are defined elsewhere // final var database = ...; final var entity1 = database.entity(Entity1.class); final var entity2 = database.entity(Entity2.class); final var sql = "SELECT DISTINCT " + String.join(", ", entity1.concatenateColumns(new Entity.ColumnsConcatenationRequest() .setPrefix("e1.").setAliasPrefix("")), entity2.concatenateColumns(new Entity.ColumnsConcatenationRequest() .setPrefix("e2.").setAliasPrefix("e2").setIgnored(Set.of("e1_id")))) + " " + "FROM " + entity1.getTable() + " e1 " + "LEFT JOIN ENTITY2 admin on e2.e1_id = e1.id " + "WHERE e1.id = ?"; final var lines = database.query(JoinModel.class, sql, b -> b.bind("the-id")); ``` ```java import io.yupiik.fusion.persistence.api.Database; import io.yupiik.fusion.persistence.api.Entity; import java.util.List; import java.util.Set; import java.util.stream.Collectors; import io.yupiik.fusion.persistence.api.Tuple2; // Assuming Entity1.class, Entity2.class are defined elsewhere // final var database = ...; final var entity1 = database.entity(Entity1.class); final var entity2 = database.entity(Entity2.class); final var e2Alias = "e2"; final var e2Ignored = Set.of("e1Id"); final var sql = "SELECT DISTINCT " + String.join(", ", entity1.concatenateColumns(new Entity.ColumnsConcatenationRequest() .setPrefix("e1.").setAliasPrefix("")), entity2.concatenateColumns(new Entity.ColumnsConcatenationRequest() .setPrefix(e2Alias + '.').setAliasPrefix(e2Alias).setIgnored(e2Ignored))) + " " + "FROM ENTITY1 e1" + " LEFT JOIN ENTITY2 admin on e2.e1_id = e1.id " + "WHERE e1.id = ?"; // precompile the binders var fields = database.entity(Entity1.class).getOrderedColumns().stream() .map(Entity.ColumnMetadata::javaName) .collect(Collectors.toList()); final var e1Binder = database.entity(Entity1.class) .mapFromPrefix("", fields.toArray(String[]::new)); fields.addAll( // continue to go through the queries fields appending the next entity ones - binder will pick the column indices right this way database.entity(Entity2.class) .getOrderedColumns().stream() .filter(c -> !e2Ignored.contains(c.javaName())) .map(c -> c.toAliasName(e2Alias)) .collect(Collectors.toList())); final var e2Binder = database.entity(Entity2.class) .mapFromPrefix(e2Alias, fields.toArray(String[]::new)); // at runtime final var lines = database.query( sql, b -> b.bind("the-id"), result -> { // bind current resultSet and iterate over each line of the resultSet return result.mapAll(line -> Tuple2.of(e1Binder.apply(line), e2Binder.apply(line))); }); // lines will get both Entity1 and Entity2 instances, then you can just filter them checking there is an id or not for example // and join them as needed to create your output model ``` -------------------------------- ### Registering a Counter Metric Source: https://github.com/yupiik/fusion/blob/master/fusion-documentation/src/main/minisite/content/fusion/observability.adoc Demonstrates how to register and increment a counter metric using the MetricsRegistry. This is useful for tracking event counts in your application. ```java import io.yupiik.fusion.observability.metrics.MetricsRegistry; import java.util.concurrent.atomic.LongAdder; @DefaultScoped public class MyService { private final LongAdder myCounter; public MyService(final MetricsRegistry registry) { this.myCounter = registry.registerCounter("my-service-counter"); } public void save(final MyEntity entity) { // do the normal business code myCounter.increment(); } } ``` -------------------------------- ### Simple Server Configuration Record Source: https://github.com/yupiik/fusion/blob/master/fusion-documentation/src/main/minisite/content/fusion/examples.adoc Defines a simple configuration record for server settings like port and access log pattern. Values are read from system properties or environment variables. ```java @RootConfiguration("server") public record ServerConfiguration(int port, String accessLogPattern) {} ``` -------------------------------- ### Map with $asList Serialization Source: https://github.com/yupiik/fusion/blob/master/fusion-documentation/src/main/minisite/content/fusion/json.adoc Illustrates how Map with '$asList' true serializes primitive values into a Properties-format string. ```java final var source = new JsonConfigurationSource(mapper, () -> new StringReader("{\"metadata\": {\"$asList\": true, \"dc\": \"us-east\", \"env\": \"prod\"}}")); // uses Properties.store() format, readable by Properties.load() final var value = source.get("metadata"); // contains "dc=us-east" and "env=prod" - 2 lines ``` -------------------------------- ### Create JsonConfigurationSource from Classpath Source: https://github.com/yupiik/fusion/blob/master/fusion-documentation/src/main/minisite/content/fusion/json.adoc Initializes a JsonConfigurationSource to read configuration from a JSON file located on the classpath. Uses ReaderSupplier for resource loading. ```java import io.yupiik.fusion.framework.api.io.ReaderSupplier; import io.yupiik.fusion.json.configuration.JsonConfigurationSource; // from classpath final var source = new JsonConfigurationSource( ReaderSupplier.fromClasspath("config.json")); ``` -------------------------------- ### JSON-RPC Endpoint Implementation in Java Source: https://github.com/yupiik/fusion/blob/master/README.adoc Implements JSON-RPC methods for finding products using the `@JsonRpc` annotation. Requires `io.yupiik.fusion.framework.api.scope.ApplicationScoped` and `io.yupiik.fusion.framework.build.api.jsonrpc.JsonRpc`. ```java import io.yupiik.fusion.framework.api.scope.ApplicationScoped; import io.yupiik.fusion.framework.build.api.jsonrpc.JsonRpc; import io.yupiik.fusion.http.server.api.Request; import io.yupiik.fusion.json.JsonMapper; import java.util.Map; @ApplicationScoped public class JsonRpcEndpoint { private final ProductService productService; public JsonRpcEndpoint(final ProductService productService) { this.productService = productService; } @JsonRpc(value = "fusion.examples.product.findAll", documentation = "Fetch all product available") public List findAllProduct(final Request request) { return productService.findProducts(); } @JsonRpc(value = "fusion.examples.product.findById", documentation = "Find a product by id") public Product findProduct(final Request request, final String id) { return productService.findProduct(id); } } ``` -------------------------------- ### Configure JSON Logging JVM Flags Source: https://github.com/yupiik/fusion/blob/master/fusion-documentation/src/main/minisite/content/fusion/kubernetes-operator.adoc Add these JVM flags to your configuration to enable JSON formatted logs using Yupiik's logging manager. ```xml -Djava.util.logging.manager=io.yupiik.logging.jul.YupiikLogManager -Dio.yupiik.logging.jul.handler.StandardHandler.formatter=json ``` -------------------------------- ### Configure TracingListener for HTTP Client Source: https://github.com/yupiik/fusion/blob/master/fusion-documentation/src/main/minisite/content/fusion/http-client.adoc Integrate tracing capabilities into the HTTP client by configuring a TracingListener. This listener requires a client tracing configuration, an accumulator for spans, an ID generator, a span evaluator, and a clock. The listener is then added to the ExtendedHttpClientConfiguration. ```java final var listener = new TracingListener( new ClientTracingConfiguration(), <1> accumulator, <2> new IdGenerator(IdGenerator.Type.HEX), <3> new ServletContextAttributeEvaluator(servletRequest), <4> systemUTC()); <5> <6> final var configuration = new ExtendedHttpClientConfiguration() .setRequestListeners(List.of(listener)); final var client = new ExtendedHttpClient(configuration); ``` -------------------------------- ### Chaining Interceptors with Stream and Function Source: https://github.com/yupiik/fusion/blob/master/fusion-documentation/src/main/minisite/content/fusion/index.adoc Shows how to chain interceptors using a Stream of Functions. Interceptors are applied in reverse order of stream definition using Function.andThen. ```java public void storeCustomer(final Customer customer) { Stream., Supplier>>of( // reversed chain of interceptor (i1 will be executed before i2) delegate -> interceptor2(Params.of(customer), delegate), delegate -> interceptor1("incoming-customer", Map.of("id", customer.id()), delegate) ) // merge the stream of interceptors as one execution wrapper .reduce(identity(), Function::andThen) .apply(() -> { // apply to the actual business logic System.out.println(">Business"); return null; }) .get(); // execute it } ``` -------------------------------- ### JSON-RPC Endpoints Source: https://github.com/yupiik/fusion/blob/master/README.adoc Provides JSON-RPC methods for interacting with product services. ```APIDOC ## fusion.examples.product.findAll ### Description Fetch all products available. ### Method JSON-RPC ### Parameters None ### Response #### Success Response - **List** - A list of product objects. ### Response Example { "example": "[{"id": "1", "name": "Example Product"}]" } ``` ```APIDOC ## fusion.examples.product.findById ### Description Find a product by its ID. ### Method JSON-RPC ### Parameters #### Request Parameters - **id** (string) - Required - The unique identifier of the product. ### Response #### Success Response - **Product** - The product object matching the provided ID. ### Response Example { "example": "{"id": "1", "name": "Example Product"}" } ``` -------------------------------- ### Add Yupiik Logging Dependency Source: https://github.com/yupiik/fusion/blob/master/fusion-documentation/src/main/minisite/content/fusion/kubernetes-operator.adoc Include the Yupiik logging dependency for runtime to enable JSON logging. ```xml io.yupiik.logging yupiik-logging-jul ${yupiik-logging.version} runtime ``` -------------------------------- ### Add Fusion API and Processor Dependencies (Maven) Source: https://github.com/yupiik/fusion/blob/master/fusion-documentation/src/main/minisite/content/fusion/setup.adoc Include the fusion-api and fusion-processor dependencies in your Maven project. The API is needed at compile time, and the processor is provided. ```xml io.yupiik.fusion fusion-api ${fusion.version} io.yupiik.fusion fusion-processor ${fusion.version} provided ``` -------------------------------- ### Configure Jib for Operator Image Source: https://github.com/yupiik/fusion/blob/master/fusion-documentation/src/main/minisite/content/fusion/kubernetes-operator.adoc Configure the Jib Maven plugin in your pom.xml to build a container image for your operator. Specify the base image, the target image name, and the main class to run. ```xml com.google.cloud.tools jib-maven-plugin 3.3.2 packaged ossyupiik/java:17.0.7@sha256:1a08a09ea4374243f28a48ec5331061d53abcdac70e51c1812b32ac4055a7deb company/operator-api:latest io.yupiik.fusion.framework.api.main.Launcher /opt/company/api-controller /opt/company/api-controller -XX:+ExitOnOutOfMemoryError ``` -------------------------------- ### Chaining Interceptors with Supplier Source: https://github.com/yupiik/fusion/blob/master/fusion-documentation/src/main/minisite/content/fusion/index.adoc Demonstrates how to chain multiple interceptors using nested Suppliers. The final .get() call triggers the execution of the entire chain. ```java public void storeCustomer(final Customer customer) { interceptor2( Params.of(customer), interceptor1( "incoming-customer", Map.of("id", customer.id()), () -> { // business code } ) ) .get(); // trigger the actual execution, it is the terminal operation for the chain } ``` -------------------------------- ### Define a Fusion CLI Command Source: https://github.com/yupiik/fusion/blob/master/fusion-documentation/src/main/minisite/content/fusion/cli.adoc Mark a bean with @Command to make it a command. Ensure it implements Runnable and has a constructor accepting the configuration class. The configuration can be customized with @RootConfiguration. ```java @Command(name = "my-commands", description = "A super command.") public class MyCommand implements Runnable { private final Conf conf; public MyCommand(final Conf conf) { this.conf = conf; } @Override public void run() { // impl what you want } @RootConfiguration("my-commands") public record Conf(String name) {} } ``` -------------------------------- ### Using @Task for Before/After Method Execution Source: https://github.com/yupiik/fusion/blob/master/fusion-documentation/src/main/minisite/content/fusion/testing.adoc Illustrates the use of the @Task annotation to execute specific code (tasks) before or after a test method. It also shows how to inject the result of a preceding task. ```java @Test @Task(phase = BEFORE, value = InsertMyData.class) @Task(phase = AFTER, value = CleanMyData.class) void run(@TaskResult(InsertMyData.class) final MyData data) { // ... } ``` -------------------------------- ### Create JsonConfigurationSource with Default Value Source: https://github.com/yupiik/fusion/blob/master/fusion-documentation/src/main/minisite/content/fusion/json.adoc Initializes a JsonConfigurationSource, providing a default JSON string if the primary resource is not found. Uses ReaderSupplier for flexible loading. ```java import io.yupiik.fusion.framework.api.io.ReaderSupplier; import io.yupiik.fusion.json.configuration.JsonConfigurationSource; // from a resource or file with a default final var source = new JsonConfigurationSource( ReaderSupplier.from("config.json", "{\"myDefaultPort\": 8080}")); ``` -------------------------------- ### Listen to an Event Source: https://github.com/yupiik/fusion/blob/master/fusion-documentation/src/main/minisite/content/fusion/examples.adoc Implement event listeners by annotating methods with `@OnEvent`. The event bus is synchronous and sorted using `@Order`. ```java public class MyListener { public void onStart(@OnEvent final Start start) { System.out.println("Application started"); } public void onStop(@OnEvent final Stop stop) { System.out.println("Application stopped"); } } ``` -------------------------------- ### Add HTTP Server Dependency Source: https://github.com/yupiik/fusion/blob/master/fusion-documentation/src/main/minisite/content/fusion/http-server.adoc Include the fusion-http-server dependency in your project's pom.xml to use the HTTP server module. ```xml io.yupiik.fusion fusion-http-server ${fusion.version} ``` -------------------------------- ### Product Endpoints Source: https://github.com/yupiik/fusion/blob/master/README.adoc Provides endpoints for managing product information. ```APIDOC ## GET /product ### Description Fetches a list of all available products. ### Method GET ### Endpoint /product ### Response #### Success Response (200) - **List** - A list of product objects. ### Response Example { "example": "[{"id": "1", "name": "Example Product"}]" } ``` ```APIDOC ## GET /product/{id} ### Description Fetches a specific product by its ID. ### Method GET ### Endpoint /product/{id} ### Parameters #### Path Parameters - **id** (string) - Required - The unique identifier of the product. ### Response #### Success Response (200) - **Product** - The product object matching the provided ID. ### Response Example { "example": "{"id": "1", "name": "Example Product"}" } ``` ```APIDOC ## POST /order ### Description Creates a new order. ### Method POST ### Endpoint /order ### Request Body - **order** (Order) - Required - The order details to be created. ### Response #### Success Response (201) - **Response** - A confirmation response, typically including the created order details. ### Response Example { "example": "{\"status\": 201, \"header\": {\"content-type\": \"application/json\"}, \"body\": \"{\"orderId\": \"abc-123\"}\"}" } ``` -------------------------------- ### Create JsonConfigurationSource from Inline String Source: https://github.com/yupiik/fusion/blob/master/fusion-documentation/src/main/minisite/content/fusion/json.adoc Initializes a JsonConfigurationSource to read configuration directly from an inline JSON string. Uses ReaderSupplier for string input. ```java import io.yupiik.fusion.framework.api.io.ReaderSupplier; import io.yupiik.fusion.json.configuration.JsonConfigurationSource; // from a file final var source = new JsonConfigurationSource( ReaderSupplier.fromInline("{\"my\":\"content\"}")); ``` -------------------------------- ### Basic Interceptor with Supplier Source: https://github.com/yupiik/fusion/blob/master/fusion-documentation/src/main/minisite/content/fusion/index.adoc Defines a simple interceptor that wraps a Supplier. The interceptor logic executes before the nested task. ```java public static Supplier interceptor1(String marker, Map data, Supplier nested) { return () -> { logger.info(message(marker, data)); // interceptor role return task.get(); // intercepted business, "ic.proceed()" in jakarta interceptor API }; } public static Supplier interceptor12(Params params, Supplier nested) { // same kind of logic for the impl } ``` -------------------------------- ### Kubernetes Deployment Manifest Source: https://github.com/yupiik/fusion/blob/master/fusion-documentation/src/main/minisite/content/fusion/kubernetes-operator.adoc Defines the Deployment for the operator controller. It specifies the container image, service account, and health check probes (readiness and liveness). ```json { "apiVersion": "apps/v1", "kind": "Deployment", "metadata": { "name": "api-controller", "namespace": "default", "labels": { "app": "api-controller" } }, "spec": { "selector": { "matchLabels": { "app": "api-controller" } }, "template": { "metadata": { "labels": { "app": "api-controller" } }, "spec": { "serviceAccountName": "api-controller", "automountServiceAccountToken": true, "containers": [ { "name": "operator-controller", "image": "company/operator-api", "readinessProbe": { "initialDelaySeconds": 4, "periodSeconds": 30, "failureThreshold": 10, "timeoutSeconds": 20, "httpGet": { "path": "/health", "port": 8081 } }, "livenessProbe": { "initialDelaySeconds": 5, "periodSeconds": 30, "failureThreshold": 10, "timeoutSeconds": 30, "httpGet": { "path": "/health", "port": 8081 } } } ] } }, "replicas": 1 } } ```