{"id":15019312,"url":"https://github.com/peter-gergely-horvath/commandmosaic","last_synced_at":"2025-10-24T09:30:50.077Z","repository":{"id":39804864,"uuid":"284301414","full_name":"peter-gergely-horvath/commandmosaic","owner":"peter-gergely-horvath","description":"Implementing Java services based on the command design pattern","archived":false,"fork":false,"pushed_at":"2022-12-16T05:18:36.000Z","size":456,"stargazers_count":4,"open_issues_count":10,"forks_count":2,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-01-31T00:41:11.066Z","etag":null,"topics":["command-pattern","http","http-server","java-application","java-service","rest","servlet","spring-boot"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/peter-gergely-horvath.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"security-jwt-spring-boot-autoconfigure/pom.xml","support":null}},"created_at":"2020-08-01T16:54:35.000Z","updated_at":"2024-12-22T09:26:16.000Z","dependencies_parsed_at":"2023-01-29T09:45:59.584Z","dependency_job_id":null,"html_url":"https://github.com/peter-gergely-horvath/commandmosaic","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/peter-gergely-horvath%2Fcommandmosaic","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/peter-gergely-horvath%2Fcommandmosaic/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/peter-gergely-horvath%2Fcommandmosaic/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/peter-gergely-horvath%2Fcommandmosaic/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/peter-gergely-horvath","download_url":"https://codeload.github.com/peter-gergely-horvath/commandmosaic/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":237944135,"owners_count":19391588,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["command-pattern","http","http-server","java-application","java-service","rest","servlet","spring-boot"],"created_at":"2024-09-24T19:53:19.019Z","updated_at":"2025-10-24T09:30:44.719Z","avatar_url":"https://github.com/peter-gergely-horvath.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# CommandMosaic: a Java command pattern framework \n\n  * [Introduction](#introduction)\n  * [Overview](#overview)\n  * [The API](#the-api)\n  * [Spring support](#spring-support)\n  * [Exposing Commands as a service](#exposing-commands-as-a-service)\n    * [Command names](#command-names)\n    * [Security](#security)\n    * [Built-in integrations for exposing commands as a service](#built-in-integrations-for-exposing-commands-as-a-service)\n    * [Using the CommandDispatcherServer server classes](#using-the-commanddispatcherserver-server-classes)\n  * [Implementing the Command Pattern](#implementing-the-command-pattern)\n    * [Command Pattern within a Plain Java application](#command-pattern-within-a-plain-java-application)\n    * [Command Pattern within a Spring Boot application](#command-pattern-within-a-spring-boot-application)\n  * [Exposing Commands from a Java application](#exposing-commands-from-a-java-application)\n    * [Exposing Commands through a Servlet (without Spring)](#exposing-commands-through-a-servlet-without-spring)\n    * [Exposing Commands from a Spring Boot application](#exposing-commands-from-a-spring-boot-application)\n  * [Servlerless Cloud with Amazon Lambda](#servlerless-cloud-with-amazon-lambda)\n    * [Plain Java AWS Lambda function (without Spring)](#plain-java-aws-lambda-function-without-spring)\n    * [Using Spring Boot 2.x+](#using-spring-boot-2x)\n    * [Are we building a monolithic Lambda application?](#are-we-building-a-monolithic-lambda-application)\n  * [Which dependency do you need](#which-dependency-do-you-need)\n  * [Spring Boot version required](#spring-boot-version-required)\n  * [Samples](#samples)\n\n\n# Introduction\n\nCommandMosaic is a project with the following high-level goals:\n\n  * Promote the implementation of business logic via the Command design pattern.\n  \n  * Support a uniform programming model across a variety of Java application types,\n    regardless of their runtime environment, including serverless cloud providers.\n    \n  * Decouple the development lifecycle of business logic from any specific \n    target runtime environment so that the same code can run both as encapsulation\n    of logic in any generic Java application or exposed as service for remote clients.\n\n  * Provide trivial-to-use, pure Java-based testing capabilities for business logic \n    developed for serverless cloud platforms without using any vendor-specific tooling. \n   \n  * Provide first class support for Spring Framework and Spring Boot features \n    (auto-configuration, dependency injection, etc) without mandating their usage.\n    \n# Overview    \n\nThe [Command design pattern](https://en.wikipedia.org/wiki/Command_pattern) is a \nwell-known pattern described in the [\"Gang of Four\"](http://wiki.c2.com/?GangOfFour)\n[Design Patterns: Elements of Reusable Object-Oriented Software](https://en.wikipedia.org/wiki/Design_Patterns)\nbook.\n\nThis Java library contains an implementation of the command pattern, \na simple programming interface for passing parameters to commands,\nand a minimalistic container for easily exposing commands as a \nsimple service with minimal amount of boilerplate code. \n\nIn addition to this, out-of-the-box support is provided for the \nindustry standard Spring Framework allowing the library consumers\nto develop their commands as pure Spring Beans, with the rich\nset of functionality offered by Spring, like transaction support, \nautomatic dependency injection through Spring's `@Autowired` \nannotation etc.\n\nThe framework is runtime-agnostic, which means it can be used in practically \nall environments, ranging from a small command line application through \nJava Servlet based systems, any Spring or Spring Boot application, including \nany serverless cloud platform, where  Java is available.\n\n# The API \n\nCommands are simple Java classes that implement the business logic in\nthe `execute` method defined in the `Command` interface. Their \nparameters are passed via fields annotated with `@Parameter` annotation, \nwhich are automatically injected by the framework.\n\n    package sample;\n\n    import org.commandmosaic.api.Command;\n    import org.commandmosaic.api.Parameter;\n    import org.commandmosaic.api.CommandContext;\n\n    public class GreetingCommand implements Command\u003cString\u003e {\n\n        @Parameter\n        String name;\n\n        @Override\n        public String execute(CommandContext context) {\n            return \"Hello \" + name;\n        }\n    }\n\n# Spring support \n\nSpring is supported out-of-the box: a Command class can also be \na Spring bean, allowing it to be used according to powerful and \nwell-known Spring concepts, including automatic dependency \ninjection through Spring's `@Autowired` annotation.    \n\n    package sample;\n\n    import org.commandmosaic.api.Command;\n    import org.commandmosaic.api.Parameter;\n    import org.commandmosaic.api.CommandContext;\n    import org.springframework.beans.factory.annotation.Autowired;\n\n    public class GreetCommand implements Command\u003cString\u003e {\n\n        @Autowired\n        private GreetingService greetingService;\n\n        @Parameter\n        private String name;\n\n        @Override\n        public String execute(CommandContext context) {\n\n            return greetingService.getMessage(name);\n        }\n    }\n\n# Exposing Commands as a service \n\nToday, the typical implementation pattern for building interactive web\napplications is using RESTful web services: that is, mapping HTTP URL patterns\nand certain HTTP operations (GET, POST, PUT and DELETE) to the respective handler code.\n\nWhile this is a nice and clear approach, there might be some drawbacks, esecially\nwith more complex applications. As the application grows, the exposed interface\nbecomes larger and larger. While Frameworks like Spring REST offer massive help\nwith the implementation, some challenges still remain:\n\n  * The service interfaces still have to be individually declared\n    * If you work with Spring, you will use @RestController, @RequestMapping etc annotations \n\t\ton the controller class. These make the declaration easy, but still: you have to write it.\n\t\n  * Dispatching logic still has to be written for each request \n    * If you work with Spring, you write the invocation of your @Service classes within \n\t\tyour @RestController. While Spring offers a great deal of support here, this part of a \n\t\tRESTful service does not give to much value and can be considered as boilerplate code. \n\t\n  * Permission management is commonly based on HTTP URL patterns and HTTP operations.\n\t  While you can surely bake your own solution, it takes time and effort to implement it properly.\n\t  \t  \nBased on this we can see the limitations of a implementing a service through via RESTful interfaces: \n\n  * Quite a lot of boilerplate coding is required\n  * The assumption that all business logic operations can be squeezed into a \n    Create/Read/Update/Delete a resource pattern\n  * The exposed interface becomes large as the application grows. This makes\n    working with the interface more complex (e.g. consider AWS API Gateway and Lambda)\n    \n   \nUnlike the traditional RESTful API pattern, CommandMosaic offers a slightly different approach:\nbuilding the application out of small blocks -- commands -- and exposing one service, that\nallows the remote clients to request the execution of a command. Security is managed at \nthe level of commands: each command simply declares who can execute it (role based security),\nbut has to know nothing how it is actually invoked.\n\nWith CommandMosaic, the only API operation exposed is dispatching of a command: this allows \nkeeping the interface minimal and focusing on the business logic instead of writing boilerplate \ncode for exposing operations for remote consumption. One simply does not have to write *any code* \nto expose a new feature implemented as a command in the application. \nThis concept makes a great deal of difference with larger and more complex application. \n\nBy default, a CommandMosaic command dispatch request is simply a JSON document sent \nto the dispatch handler via HTTP POST with similar structure:\n\n    {\n        \"command\": \"Foobar\",\n        \"parameters\" : {\n            \"foo\": \"Hello there\",\n            \"bar\": 42\n        },\n        \"protocol\": \"CM/1.0\"    \n    }\n\n## Command names\n\nExposing the full package structure of the application in remote scenarios would be\nespecially undesirable. To prevent unwanted coupling and to reduce overall message size,\nCommandMosaic uses abbreviated command names, where command names do not contain the \ncommon root package name prefix configured during the creation of the CommandDispatcher\nand use forward slash (\"/\") instead of the dot (\".\") package separator.\n  \nFor example, assuming the `CommandDispatcher` used was configured with `org.acme` as the \nroot package, the following request would cause the command `org.acme.foo.bar.Foobar` \nto be executed:\n\n    {\n        \"command\": \"foo/bar/Foobar\",\n        \"protocol\": \"CM/1.0\"    \n    }\n\n## Security \n\nIn remote service cases, having proper security is essential so that commands\ncan only be executed by authorized clients only.  \nThe module [commandmosaic-security](https://github.com/peter-gergely-horvath/commandmosaic/tree/master/security) \ncontains support features for this requirement.\n\nTwo annotations are provided to mark the access levels of each commands:\n\n  * `org.commandmosaic.security.annotation.Access.IsPublic`:\n    This annotation must be applied to all command classes that should be\n    available without authentication.\n    \n  * `org.commandmosaic.security.annotation.Access.RequiresAnyOfTheAuthorities`\n    This annotation must be applied to all command classes that should only\n    be available to authenticated clients. Optionally, role based security\n    can be implemented by specifying the roles which should have access to \n    the specific command.\n     \nAccess control is implemented via `CommandInterceptor`s: application developers\nare required to develop a custom interceptor by extending the framework-provided\nclass `org.commandmosaic.security.interceptor.DefaultSecurityCommandInterceptor`\nand configure it for the `CommandDispatcher`. \n\n`org.commandmosaic.security.interceptor.DefaultSecurityCommandInterceptor`\nprovides a base implementation for security `CommandInterceptor`s: its \n`attemptLogin(CommandContext)` method must be implemented by the end-user.\nSuch implementations will want to extract the user-defined \nauthentication/authorization information from the request via the \n`CommandContext.getAuth()` method.\n\nThe user-provided security `CommandInterceptor` must be configured within\n`CommandDispatcherConfiguration`, otherwise security will not be enabled. \n\n    CommandDispatcherConfiguration configuration = CommandDispatcherConfiguration.builder()\n        .rootPackage(\"com.acme.foobar\")\n        .interceptor(MyCustomSecurityCommandInterceptor.class)\n        .build();\n    \n### Message \"auth\" field\n\nEach command dispatch request can have a user defined, field \"`auth`\", which holds\nkey-value pairs: when security is enabled, this must be provided for all requests\nthat dispatch a command marked with `@RestrictedAccess` annotation. \n\nThe content of the field is user-defined key value pairs; the only restriction is \nthat it must be deserializable to a `HashMap`.\n\nFor example, the following sample shows passing two fields in the \"`auth`\" Map field,\n`username` and `password`. \n\n    {\n      \"command\": \"foo/bar/Foobar\",\n      \"auth\": {\n        \"username\": \"foo\",\n        \"password\": \"bar\"\n      },\n      \"protocol\": \"CM/1.0\"\n    }  \n\n\nThese values can be extracted from the `CommandContext` via the `Map`\nreturned by `CommandContext.getAuth()` method. The user's implementation\nof `attemptLogin(CommandContext)` must authenticate the request: throw an\n`AuthenticationException` in case login fails, otherwise return the roles\nassociated with the user. (The rest of the security management is handled\nby the framework code in `AbstractSecurityCommandInterceptor`)\n    \n    package sample;\n    \n    import org.commandmosaic.api.CommandContext;\n    import org.commandmosaic.security.AuthenticationException;\n    import org.commandmosaic.security.interceptor.DefaultSecurityCommandInterceptor;\n    \n    import java.util.Map;\n    import java.util.Set;\n    \n    public class MyCustomSecurityCommandInterceptor extends AbstractSecurityCommandInterceptor {\n    \n        @Override\n        protected Set\u003cString\u003e attemptLogin(CommandContext commandContext) throws AuthenticationException {\n            Map\u003cString, Object\u003e auth = commandContext.getAuth();\n    \n            String username = (String) auth.get(\"username\");\n            String password = (String) auth.get(\"password\");\n    \n            // throw AuthenticationException if login fails, otherwise retrieve user roles\n    \n            Set\u003cString\u003e rolesOfTheUser = // retrieve user roles ...\n    \n            return rolesOfTheUser;\n        }\n    }\n    \n## Built-in integrations for exposing commands as a service\n\nThe following integrations are provided out-of-the-box:\n  * Servlet\n  * Spring HTTP Request handlers\n  * Amazon AWS Lambda (with and without Spring Boot)\n\n## Using the CommandDispatcherServer server classes\n\nThis library was designed with the goal of exposing commands as services \nwith minimum amount of code. The API \n`org.commandmosaic.api.server.CommandDispatcherServer` provides\n a layer of abstraction between how a command dispatch request is \ntransmitted and represented, and the actual `CommandDispatcher` being used.   \n\nA `CommandDispatcherServer` reads the incoming dispatch request from\na `java.io.InputStream` and writes the outcome of the command execution to \n`java.io.OutputStream`. Any container that can provide incoming messages\nas `java.io.InputStream` and can receive the response as bytes being written\nto a `java.io.OutputStream` can easily be integrated.\n\nThe class `org.commandmosaic.core.server.DefaultCommandDispatcherServer`\noffers a default implementation for building the dispatcher server. \n\nIts constructor takes a `CommandDispatcher` that it will use to dispatch \nincoming requests. Its only public method `serviceRequest` reads \nthe dispatch requests from the supplied `InputStream` as JSON and writes the \nresponse back to the `OutputStream` as JSON as well. This allows easy integration\nto any request handling mechanism where the application has access to the request\nstreams. (For example: Apache Netty network servers etc.)\n\n\n# Implementing the Command Pattern\n\n## Command Pattern within a Plain Java application \n\nThe simplest case is using the `CommandDispatcher` API for implementing\nCommand Pattern in a Java application, without exposing commands as a service.\nHere, one only uses the library for organizing code in a modular and re-usable \nstructure.  \n\n### Dependency\n\nAdd the following dependency declaration to your Maven `pom.xml`. \n(or its equivalent in your other preferred build tool), replacing \nLATEST with the available latest version: \n\n    \u003cdependency\u003e\n        \u003cgroupId\u003eorg.commandmosaic\u003c/groupId\u003e\n        \u003cartifactId\u003ecommandmosaic-plain-java\u003c/artifactId\u003e\n        \u003cversion\u003eLATEST\u003c/version\u003e\n    \u003c/dependency\u003e \n\n### Description \n\nFor this use-case, one constructs a \n`CommandDispatcherConfiguration` object using its builder and then calls\nuses the corresponding \"plain-Java\" `CommandDispatcherFactory` to construct\na `CommandDispatcher`. The `rootPackage` specified acts as a restriction for the \n`CommandDispatcher`: it will only accept commands that are located in the specified\npackage or any of its subpackages. In the sample below, the `dispatchCommand`\nmethod call would throw an Exception for any commands that are outside\nof the root package `com.acmecorp.foobarapp.sample`. This explicit definition\nensures only the intended commands can be executed by a given `CommandDispatcher`.\nAt the same time, one application can host an arbitrary number of `CommandDispatcher`s.\n\n\n    package org.commandmosaic.plain.sample;\n    \n    import org.commandmosaic.api.Command;\n    import org.commandmosaic.api.CommandContext;\n    import org.commandmosaic.api.CommandDispatcher;\n    import org.commandmosaic.api.Parameter;\n    import org.commandmosaic.api.configuration.CommandDispatcherConfiguration;\n    import org.commandmosaic.api.factory.CommandDispatcherFactory;\n    import org.commandmosaic.plain.PlainCommandDispatcherFactory;\n    \n    public class SampleApplication {\n    \n        public static void main(String[] args) {\n    \n            CommandDispatcherConfiguration configuration = CommandDispatcherConfiguration.builder()\n                    .rootPackageFromClass(SampleApplication.class)\n                    .build();\n    \n            CommandDispatcherFactory factory = PlainCommandDispatcherFactory.getInstance();\n            CommandDispatcher commandDispatcher = factory.getCommandDispatcher(configuration);\n    \n            GreetingCommand greetingCommand = new GreetingCommand(\"John Smith\");\n            String result = commandDispatcher.dispatchCommand(greetingCommand, null);\n    \n            System.out.println(result);\n        }\n    \n        public static class GreetingCommand implements Command\u003cString\u003e {\n    \n            @Parameter\n            private String name;\n    \n            public GreetingCommand() {\n                // no argument constructor is required for the framework\n            }\n    \n            public GreetingCommand(String name) {\n                this.name = name;\n            }\n    \n            @Override\n            public String execute(CommandContext context) {\n                return \"Hello \" + name;\n            }\n        }\n    }\n    \n    \nSee [sample application](https://github.com/peter-gergely-horvath/commandmosaic/tree/master/sample-apps/commandmosaic-helloworld-sample-app)\n    \n## Command Pattern within a Spring Boot application\n\nThe library provides out-of-the-box support for Spring Boot. You can get the \nlibrary to automatically initialize by Spring Boot and develop your commands \nas Spring Beans, with the rich set of functionality offered by Spring, like \ntransaction support, automatic dependency injection through Spring's \n`@Autowired` annotation etc.\n\n### Dependency\n\nAdd the following dependency declaration to your Maven `pom.xml`. \n(or its equivalent in your other preferred build tool), replacing \nLATEST with the available latest version: \n\n    \u003cdependency\u003e\n        \u003cgroupId\u003eorg.commandmosaic\u003c/groupId\u003e\n        \u003cartifactId\u003ecommandmosaic-spring-boot-autoconfigure\u003c/artifactId\u003e\n        \u003cversion\u003eLATEST\u003c/version\u003e\n    \u003c/dependency\u003e\n\n### Description \n\nWith the `commandmosaic-spring-boot-autoconfigure` you can rely on\nSpring Boot library auto-configuration: simply create a `CommandDispatcherConfiguration` \nand expose it as a Spring bean. \n\n\n\t@Bean\n\tpublic CommandDispatcherConfiguration springCommandDispatcherConfiguration() {\n\t\treturn CommandDispatcherConfiguration.builder()\n\t\t\t\t.rootPackage(\"com.acme.foobar.commands\")\n\t\t\t\t.build();\n\t}\n\nOnce done, you can simply rely on standard Spring auto-wiring to receive the reference to\nthe Spring-aware `CommandDispatcher` instance.\n\n\n    @Service\n\tpublic class FoobarServiceImpl implements FoobarService {\n\n\t\tprivate final CommandDispatcher commandDispatcher;\n\n\t\t@Autowired\n\t\tpublic FoobarServiceImpl(CommandDispatcher commandDispatcher) {\n\t\t\tthis.commandDispatcher = commandDispatcher;\n\t\t}\n\t\t\n\t\t// ... use the CommandDispatcher\n\t\t\n\t}\n \nSee [sample application](https://github.com/peter-gergely-horvath/commandmosaic/tree/master/sample-apps/commandmosaic-springboot2-sample-app)\n\n# Exposing Commands from a Java application\n\n## Exposing Commands through a Servlet (without Spring)\n\nCommands can be exposed as a lightweight REST service,\nwhere only one operation, the dispatching of a command is published.\nThe implementation is inside a framework-provided servlet class\nthat expects the same JSON document format as other runtime environments\nuse. The users of this library has to configure CommandDispatcherServlet\nbundled within the framework, after which they have to just start\nwriting their command implementation. \n\nA request is simply a JSON document, with similar structure:\n\n    {\n        \"command\": \"Foobar\",\n        \"parameters\" : {\n            \"foo\": \"Hello there\",\n            \"bar\": 42\n        },\n        \"protocol\": \"CM/1.0\"    \n    }\n\n### Dependency\n\nAdd the following dependency declaration to your Maven `pom.xml`. \n(or its equivalent in your other preferred build tool), replacing \nLATEST with the available latest version: \n\n    \u003cdependency\u003e\n        \u003cgroupId\u003eorg.commandmosaic\u003c/groupId\u003e\n        \u003cartifactId\u003ecommandmosaic-servlet\u003c/artifactId\u003e\n        \u003cversion\u003eLATEST\u003c/version\u003e\n    \u003c/dependency\u003e \n\n### Description \n\nConfigure the `org.commandmosaic.http.servlet.CommandDispatcherServlet` Servlet \nprovided by the framework for the desired URL and configure it using initialization\nparameters according to the following:\n\n  * The **root package** of the CommandDispatcher MUST be specified in a\n    String initialization parameter, the name of which is stored in \n    `CommandDispatcherServlet.COMMAND_DISPATCHER_ROOT_PACKAGE`\n    \n  * Optionally, **command interceptor classes** can be specified as\n    comma separated list of fully qualified class names passed in a String \n    initialization parameter, the name of which is stored in \n    `CommandDispatcherServlet.COMMAND_DISPATCHER_ROOT_PACKAGE`\n\nYou will likely want to secure access to particular commands and\nimplement proper authentication and access management (authorization).\nFor this, please refer to the features of [commandmosaic-security](https://github.com/peter-gergely-horvath/commandmosaic/tree/master/security)\nmodule, which offers standardised annotation based access control and an abstract\n`CommandInterceptor` base class for plugging in custom authentication and authorization\nlogic with minimal amount of code.\n\n## Exposing Commands from a Spring Boot application\n\nCommands can be exposed as a lightweight REST service,\nwhere only one operation, the dispatching of a command is published.\nThe library provides out-of-the-box support for Spring Boot. You can get the \nlibrary to automatically initialize by Spring Boot and develop your commands \nas Spring Beans, with the rich set of functionality offered by Spring, like \ntransaction support, automatic dependency injection through Spring's \n`@Autowired` annotation etc.\n\nA request is simply a JSON document, with similar structure:\n\n    {\n        \"command\": \"Foobar\",\n        \"parameters\" : {\n            \"foo\": \"Hello there\",\n            \"bar\": 42\n        },\n        \"protocol\": \"CM/1.0\"    \n    }\n\n\n### Dependency\n\nAdd the following dependency declaration to your Maven `pom.xml`. \n(or its equivalent in your other preferred build tool), replacing \nLATEST with the available latest version: \n\n    \u003cdependency\u003e\n        \u003cgroupId\u003eorg.commandmosaic\u003c/groupId\u003e\n        \u003cartifactId\u003ecommandmosaic-spring-boot-autoconfigure\u003c/artifactId\u003e\n        \u003cversion\u003eLATEST\u003c/version\u003e\n    \u003c/dependency\u003e\n\n### Description \n\nWith the `commandmosaic-spring-boot-autoconfigure` you can rely on\nSpring Boot library auto-configuration: simply create a `CommandDispatcherConfiguration` \nand expose it as a Spring bean. \n\n    package sample.app.config;\n    \n    import org.commandmosaic.api.configuration.CommandDispatcherConfiguration;\n    import org.springframework.context.annotation.Bean;\n    import org.springframework.context.annotation.Configuration;\n    \n    @Configuration\n    public class SampleAppConfig {\n    \n        /* other configuration entries... */\n    \n    \t@Bean\n    \tpublic CommandDispatcherConfiguration springCommandDispatcherConfiguration() {\n    \t\treturn CommandDispatcherConfiguration.builder()\n    \t\t\t\t.rootPackage(\"com.acme.foobar.commands\")\n    \t\t\t\t.build();\n    \t}\n    \n    }\n\nOnce done, you can simply expose the `CommandDispatcherServer`\nthrough a Spring Web REST RestController class similar to the one below.\n(Again: we rely on Spring to configure the dependencies for us.)\n\n    package sample;\n    \n    import org.commandmosaic.api.server.CommandDispatcherServer;\n    \n    import org.springframework.web.bind.annotation.PostMapping;\n    import org.springframework.web.bind.annotation.RequestMapping;\n    import org.springframework.web.bind.annotation.RestController;\n    \n    import java.io.IOException;\n    import java.io.InputStream;\n    import java.io.OutputStream;\n    \n    @RestController\n    @RequestMapping(\"/api\")\n    public class CommandResource {\n    \n        private final CommandDispatcherServer commandDispatcherServer;\n    \n        public CommandResource(CommandDispatcherServer commandDispatcherServer) {\n            this.commandDispatcherServer = commandDispatcherServer;\n        }\n    \n    \n        @PostMapping(\"/cmd\")\n        public void processCommand(InputStream is, OutputStream os) throws IOException {\n            commandDispatcherServer.serviceRequest(is, os);\n        }\n    }\n\n# Servlerless Cloud with Amazon Lambda\n\nAmazon Lambda (Java) is supported out-of-the-box. Different flavours of this library \n(Plain Java and Spring Boot support) provide abstract AWS `RequestHandler` base \nimplementations that dispatch the command specified. \n  \nThe benefit of using CommandMosaic with Amazon Lambda is the small interface\nfootprint. You deploy you Lambda application with one AWS RequestHandler and\nconfigure AWS API Gateway with one HTTP resource. You then can add further \ncommands to your code base without having to even touch the existing AWS \nAPI Gateway configuration as the only operation exposed is dispatching a \ncommand. These commands can easily be tested in a Junit / TestNG test or\nyou can use the standard Servlet or Spring HttpRequestHandler containers to \nstart a mock server for an full-blown integration test, which will provide \nexactly the same behaviour as the container running in the cloud (as the \ncore behaviour is shared across all runtime environments).\n   \nWhen using CommandMosaic with Amazon Lambda, you, as the user of the \nframework have to subclass the appropriate base `RequestHandler` class with a \nplaceholder class, that does nothing apart from passing configuration to the \nframework-provided superclass's constructor. This placeholder class has to be configured as your \nlambda function: the framework provides the behaviour, while your placeholder \nsub-class provides the configuration only. \n\nOnce this is done, you can start implementing your `Command` classes and then \npackage your application. The framework-provided `RequestHandler` base \ndispatches incoming requests to the corresponding commands. All you have to\ndo is:\n  1. Implement your business logic as commands\n  2. Package the application properly for AWS Lambda and deploy it\n  1. Configure the source trigger (e.g. AWS API Gateway) for your lambda function \n \nYou need to ensure that the application is packaged according to AWS requirements. \nYou are encouraged to create an AWS Java lambda application skeleton using \nAWS Maven archetype and then add the corresponding library dependency. \n \n## Plain Java AWS Lambda function (without Spring)\n\nUse this if you want to implement your AWS Lambda function without\nusing Spring or Spring Boot at all.\n\n### Dependency\n\nAdd the following dependency declaration to your Maven `pom.xml`. \n(or its equivalent in your other preferred build tool), replacing \nLATEST with the available latest version: \n\n        \u003cdependency\u003e\n            \u003cgroupId\u003eorg.commandmosaic\u003c/groupId\u003e\n            \u003cartifactId\u003ecommandmosaic-aws-lambda-plain-java\u003c/artifactId\u003e\n            \u003cversion\u003eLATEST\u003c/version\u003e\n        \u003c/dependency\u003e \n\n### Java module declaration\n\nWhen using the Java Platform Module System (\"Java 9+ modules\"), add \nsimilar settings to your `module-info.java` module descriptor file.\n(*NOTE: the sample below uses `sampleapp` as module name: do not forget to\nsubstitute your own module name*)\n\n    module sampleapp {\n    \n        requires org.commandmosaic.aws.lambda.plain;\n    \n        opens sampleapp to\n                org.commandmosaic.core;\n    }\n\n### Description \n\nOnce the dependency is added, create a placeholder Java request handler class in your \nAWS Java lambda application that subclasses  \n`org.commandmosaic.aws.lambda.plain.PlainLambdaCommandDispatcherRequestHandler`\nand has a no-argument constructor, which invokes the `super` constructor with the \ndesired `CommandDispatcherConfiguration` configuration object. \n\nOnce this is done, you can start implementing your `Command` classes and then \npackage your application. Your `Command` classes are Spring beans, so you\ncan easily use Spring `@Autowired` depdency injection and other Spring features.\n\nThe framework-provided `RequestHandler` base \ndispatches incoming requests to the corresponding commands. All you have to\ndo is:\n  1. Implement your business logic as commands\n  2. Package the application properly for AWS Lambda and deploy it\n  1. Configure the source trigger (e.g. AWS API Gateway) for your lambda function \n \nNOTE: You need to ensure that the application is packaged according to AWS requirements. \nYou are encouraged to create an AWS Java lambda application skeleton using \nAWS Maven archetype and then add the corresponding library dependency. \n\n## Using Spring Boot 2.x+\n\n### Dependency\n\nAdd the following dependency declaration to your Maven `pom.xml`. \n(or its equivalent in your other preferred build tool), replacing \nLATEST with the available latest version: \n\n        \u003cdependency\u003e\n            \u003cgroupId\u003eorg.commandmosaic\u003c/groupId\u003e\n            \u003cartifactId\u003ecommandmosaic-aws-lambda-springboot\u003c/artifactId\u003e\n            \u003cversion\u003eLATEST\u003c/version\u003e\n        \u003c/dependency\u003e \n\n\n### Java module declaration\n\nWhen using the Java Platform Module System (\"Java 9+ modules\"), add \nsimilar settings to your `module-info.java` module descriptor file.\n(*NOTE: the sample below uses `sampleapp` as module name: do not forget to\nsubstitute your own module name*)\n\n    module sampleapp {\n    \n        requires org.commandmosaic.aws.lambda.springboot;\n    \n        requires spring.boot.autoconfigure;\n        requires spring.boot;\n        requires spring.context;\n        requires spring.beans;\n    \n        opens sampleapp to\n                spring.core, spring.context, spring.beans,\n                org.commandmosaic.core;\n    }\n\n### Description \n\nOnce the dependency is added, create a placeholder Java request handler class in \nyour AWS Java lambda application that subclasses  \n`org.commandmosaic.aws.lambda.springboot.SpringBootLambdaCommandDispatcherRequestHandler`\nand has a no-argument constructor, which invokes the `super` constructor with the desired\nconfiguration, passing the class of the Spring Boot application class and optionally, \nthe profiles used.\n\n    package sample;\n\n    import org.commandmosaic.aws.lambda.springboot.SpringBootLambdaCommandDispatcherRequestHandler;\n\n    public class SampleApplicationRequestHandlerSpringBootLambda extends SpringBootLambdaCommandDispatcherRequestHandler {\n\n        public SampleApplicationRequestHandlerSpringBootLambda() {\n            super(SampleApplication.class);\n        }\n    }\n\nOnce this is done, you can start implementing your `Command` classes and then \npackage your application. Your `Command` classes are Spring beans, so you\ncan easily use Spring `@Autowired` depdency injection and other Spring features.\n\nThe framework-provided `RequestHandler` base \ndispatches incoming requests to the corresponding commands. All you have to\ndo is:\n  1. Implement your business logic as commands\n  2. Package the application properly for AWS Lambda and deploy it\n  1. Configure the source trigger (e.g. AWS API Gateway) for your lambda function \n \nNOTE: You need to ensure that the application is packaged according to AWS requirements. \nYou are encouraged to create an AWS Java lambda application skeleton using \nAWS Maven archetype and then add the corresponding library dependency. \n\nPlease check the sample application for a fully working project setup:\n[commandmosaic-aws-lambda-springboot2-sample-app](https://github.com/peter-gergely-horvath/commandmosaic/tree/master/sample-apps/commandmosaic-aws-lambda-springboot2-sample-app)\n\n## Are we building a monolithic Lambda application?\n\nThe official recommendation from Amazon regarding Lambda functions is to use \na separate function for every single operation and use further of their orchestration\nservices (e.g. AWS Step Functions) to manage the cooperation, fully distributing and de-coupling\nmicroservices to the point where they are not maintained in the same code repository anymore.\n\nApplications written using this library indeed can be considered as a monolithic application, \nhowever in my opinion this approach can actually be better in a number of cases, as\n 1. You have all the application logic in place \n 2. Refactorings are trivial with the help of a good IDE\n 3. You only have one API to maintain, which can expose a large number of operations\n 4. You still can use AWS services (e.g. API Gateway) to host multiple instances of the same application\n \n\n\n\n# Which dependency do you need\n\nPlease select the artifactId based on the following table. \nYou always want to pick **only one** of the following dependencies:\n\n| Use-case                           | Dependency artifactId                    |\n| -----------------------------------|:----------------------------------------:|\n| Plain Java application, no Spring  | `commandmosaic-plain-java`               |\n| Java application with Spring       | `commandmosaic-spring`                   |\n| Java application with Spring Boot  | `commandmosaic-spring-boot-autoconfigure`|\n| AWS Java Lambda, no Spring         | `commandmosaic-aws-lambda-plain-java`    |\n| AWS Java Lambda, with Spring Boot  | `commandmosaic-aws-lambda-springboot`    |\n\n# Spring Boot version required\n\nAs \n[Spring Boot 1.x has been deprecated and is no longer supported by Pivotal](https://spring.io/blog/2019/08/06/it-is-time-goodbye-spring-boot-1-x), \nSpring Boot 1.x is not (and will not be) supported at all.\n\nPlease always use Spring Boot 2.x+ versions with this library. \n\n# Samples \nYou are encouraged to check the sample applications: please download the sample application \nprojects referenced below. Before you can work with the sample project, **you need to make\nadjustments to the project `pom.xml` file**:\n\n 1. Remove the `\u003cparent\u003e...\u003c/parent\u003e` section  \n 2. Uncomment the sections commented out: this provides a working build configuration \n 3. Adjust groupId/artifactId to your needs \n\n * [Hello World application](https://github.com/peter-gergely-horvath/commandmosaic/tree/master/sample-apps/commandmosaic-helloworld-sample-app)\n * [Minimalistic console Spring Boot2 application](https://github.com/peter-gergely-horvath/commandmosaic/tree/master/sample-apps/commandmosaic-springboot2-sample-app)\n * [Exposing commands via an AWS Lambda function (request handler)](https://github.com/peter-gergely-horvath/commandmosaic/tree/master/sample-apps/commandmosaic-aws-lambda-springboot2-sample-app)\n\n \n \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpeter-gergely-horvath%2Fcommandmosaic","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpeter-gergely-horvath%2Fcommandmosaic","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpeter-gergely-horvath%2Fcommandmosaic/lists"}