{"id":48203119,"url":"https://github.com/saicone/delivery4j","last_synced_at":"2026-04-04T18:29:26.683Z","repository":{"id":215832936,"uuid":"739881613","full_name":"saicone/delivery4j","owner":"saicone","description":"Java library facade to send messages using mutliple data delivery concepts","archived":false,"fork":false,"pushed_at":"2026-04-02T00:02:16.000Z","size":535,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-04-02T11:52:20.042Z","etag":null,"topics":["activemq","hikari","java","kafka","nats","polling","postgres","postgresql","rabbitmq","redis","sql"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/saicone.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":"Rubenicos"}},"created_at":"2024-01-06T20:36:04.000Z","updated_at":"2026-04-02T00:02:20.000Z","dependencies_parsed_at":"2026-04-02T06:03:35.233Z","dependency_job_id":null,"html_url":"https://github.com/saicone/delivery4j","commit_stats":null,"previous_names":["saicone/delivery4j"],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/saicone/delivery4j","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saicone%2Fdelivery4j","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saicone%2Fdelivery4j/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saicone%2Fdelivery4j/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saicone%2Fdelivery4j/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/saicone","download_url":"https://codeload.github.com/saicone/delivery4j/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saicone%2Fdelivery4j/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31408608,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-04T10:20:44.708Z","status":"ssl_error","status_checked_at":"2026-04-04T10:20:06.846Z","response_time":60,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["activemq","hikari","java","kafka","nats","polling","postgres","postgresql","rabbitmq","redis","sql"],"created_at":"2026-04-04T18:29:24.510Z","updated_at":"2026-04-04T18:29:26.671Z","avatar_url":"https://github.com/saicone.png","language":"Java","readme":"\u003ch1 align=\"center\"\u003eDelivery4j\u003c/h1\u003e\n\n\u003ch4 align=\"center\"\u003eJava library facade for multiple data delivery concepts.\u003c/h4\u003e\n\n\u003cp align=\"center\"\u003e\n    \u003ca href=\"https://saic.one/discord\"\u003e\n        \u003cimg src=\"https://img.shields.io/discord/974288218839191612.svg?style=flat-square\u0026label=discord\u0026logo=discord\u0026logoColor=white\u0026color=7289da\"/\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://www.codefactor.io/repository/github/saicone/delivery4j\"\u003e\n        \u003cimg src=\"https://www.codefactor.io/repository/github/saicone/delivery4j/badge?style=flat-square\"/\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://github.com/saicone/delivery4j\"\u003e\n        \u003cimg src=\"https://img.shields.io/github/languages/code-size/saicone/delivery4j?logo=github\u0026logoColor=white\u0026style=flat-square\"/\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://jitpack.io/#com.saicone/delivery4j\"\u003e\n        \u003cimg src=\"https://jitpack.io/v/com.saicone/delivery4j.svg?style=flat-square\"/\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://javadoc.saicone.com/delivery4j/overview-summary.html\"\u003e\n        \u003cimg src=\"https://img.shields.io/badge/JavaDoc-Online-green?style=flat-square\"/\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://docs.saicone.com/delivery4j/\"\u003e\n        \u003cimg src=\"https://img.shields.io/badge/Saicone-delivery4j%20Wiki-3b3bb0?logo=github\u0026logoColor=white\u0026style=flat-square\"/\u003e\n    \u003c/a\u003e\n\u003c/p\u003e\n\nThere are multiple ways to transfer data between Java applications, this library offers an easy way to connect with them using common methods.\n\nCurrently supporting the brokers:\n\n* [ActiveMQ](https://github.com/apache/activemq) using topic producers and consumers.\n* [Kafka](https://github.com/apache/kafka) using empty-key records to producers.\n* [NATS](https://github.com/nats-io/nats.java) using subject subscription.\n* [PostgreSQL](https://github.com/pgjdbc/pgjdbc) using `LISTEN` and `NOTIFY` statement.\n* [RabbitMQ](https://github.com/rabbitmq/rabbitmq-java-client) using queue and consumer via exchange.\n* [Redis](https://github.com/redis/jedis) using publish and subscribe (also compatible with [KeyDB](https://github.com/Snapchat/KeyDB)).\n* SQL polling (not a real broker, but can be used as one).\n* [Valkey](https://github.com/valkey-io/valkey-java) using publish and subscribe (same as Redis, but with an older API).\n\nPostgreSQL and SQL are also compatible with [Hikari](https://github.com/brettwooldridge/HikariCP).\n\n## Dependency\n\nDelivery4j contains the following artifacts:\n\n* `delivery4j` - The main project.\n* `broker-activemq` - ActiveMQ broker.\n* `broker-kafka` - Kafka broker.\n* `broker-nats` - NATS broker.\n* `broker-postgresql` - PostgreSQL broker using plain Java connections.\n* `broker-postgresql-hikari` - PostgreSQL broker using Hikari library.\n* `broker-postgresql-hikari-java8` - PostgreSQL broker using Hikari 4.x (for Java 8).\n* `broker-rabbitmq` - RabbitMQ broker.\n* `broker-redis-jedis` - Redis broker using [jedis](https://github.com/redis/jedis) library.\n* `broker-sql` - SQL broker using plain Java connections.\n* `broker-sql-hikari` - SQL broker using Hikari library.\n* `broker-sql-hikari-java8` - SQL broker using Hikari 4.x (for Java 8).\n* `broker-valkey` - Valkey broker.\n* `extension-caffeine` - Extension to detect and use Caffeine cache on MessageChannel.\n* `extension-guava` - Extension to detect and use Guava cache on MessageChannel.\n\n\u003cdetails\u003e\n  \u003csummary\u003ebuild.gradle\u003c/summary\u003e\n\n```groovy\nrepositories {\n    maven { url 'https://jitpack.io' }\n}\n\ndependencies {\n    implementation 'com.saicone.delivery4j:delivery4j:1.1.5'\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003ebuild.gradle.kts\u003c/summary\u003e\n\n```kotlin\nrepositories {\n    maven(\"https://jitpack.io\")\n}\n\ndependencies {\n    implementation(\"com.saicone.delivery4j:delivery4j:1.1.5\")\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003epom.xml\u003c/summary\u003e\n\n```xml\n\u003crepositories\u003e\n    \u003crepository\u003e\n        \u003cid\u003eJitpack\u003c/id\u003e\n        \u003curl\u003ehttps://jitpack.io\u003c/url\u003e\n    \u003c/repository\u003e\n\u003c/repositories\u003e\n\n\u003cdependencies\u003e\n    \u003cdependency\u003e\n        \u003cgroupId\u003ecom.saicone.delivery4j\u003c/groupId\u003e\n        \u003cartifactId\u003edelivery4j\u003c/artifactId\u003e\n        \u003cversion\u003e1.1.5\u003c/version\u003e\n        \u003cscope\u003ecompile\u003c/scope\u003e\n    \u003c/dependency\u003e\n\u003c/dependencies\u003e\n```\n\n\u003c/details\u003e\n\n## Usage\n\nHow to use Delivery4j library.\n\n### Broker\n\nUsing brokers is pretty simple, you just need to create a broker instance (depending on the implementation) and set a consumer.\n\n```java\nBroker broker = // Create instance from any implementation\n\n// Subscribe to channels\nbroker.subscribe(\"hello:world\", \"myChannel1\");\n\nbroker.setConsumer((channel, data) -\u003e {\n    // do something\n});\n\n// Start connection\nbroker.start();\n\n// Send data\nbyte[] data = ...;\n\nbroker.send(\"myChannel1\", data);\n```\n\nSome brokers require to convert bytes to String and viceversa, Base64 is used by default.\n\n```java\nBroker broker = // Create instance from any implementation\n\nbroker.setCodec(new ByteCodec\u003c\u003e() {\n    @Override\n    public @NotNull String encode(byte[] src) {\n        // convert bytes to String\n    }\n\n    @Override\n    public byte[] decode(@NotNull String src) {\n        // convert String to bytes\n    }\n});\n```\n\nSome brokers have blocking operations or repetitive tasks, it's suggested to implement your own executor.\n\n```java\nBroker broker = // Create instance from any implementation\n\nbroker.setExecutor(new DelayedExecutor\u003cMyTaskObject\u003e() {\n    @Override\n    public @NotNull MyTaskObject execute(@NotNull Runnable command) {\n        // run task and return itself\n    }\n\n    @Override\n    public @NotNull MyTaskObject execute(@NotNull Runnable command, long delay, @NotNull TimeUnit unit) {\n        // run delayed task and return itself\n    }\n\n    @Override\n    public @NotNull MyTaskObject execute(@NotNull Runnable command, long delay, long period, @NotNull TimeUnit unit) {\n        // run repetitive task and return itself\n    }\n\n    @Override\n    public void cancel(@NotNull MyTaskObject unused) {\n        // cancel task\n    }\n});\n```\n\nAnd also a logging instance to log information about connection and exceptions, by default it use the best available implementation.\n\nIt uses a number terminology for logging levels:\n\n1. Error\n2. Warning\n3. Information\n4. Debug\n\n```java\nBroker broker = ...;\n\n// --- Using existing logger instance\nLogger logger = ...;\nbroker.setLogger(LogFilter.valueOf(logger, 3)); // using 3 as max logging level\nbroker.setLogger(LogFilter.valueOf(logger, () -\u003e 3)); // you can also supply the max level dynamically\n\n// --- Creating a logger instance from name\nbroker.setLogger(LogFilter.valueOf(\"LogName\", 3));\nbroker.setLogger(LogFilter.valueOf(\"LogName\", () -\u003e 3));\n\n// --- Creating a logger instance from class\nbroker.setLogger(LogFilter.valueOf(MyObject.class, 3));\nbroker.setLogger(LogFilter.valueOf(MyObject.class, () -\u003e 3));\n```\n\n### Messenger\n\nProbably the reason why you are here, it's a simple usage of brokers to send and receive multi-line String messages.\n\nFirst you need to extend AbstractMessenger and provide a broker.\n\n```java\npublic class Messenger extends AbstractMessenger {\n    @Override\n    protected Broker loadBroker() {\n        // Create instance from any implementation\n    }\n}\n```\n\nAnd then use the Messenger.\n\n```java\nMessenger messenger = new Messenger();\n\n// Start connection\nmessenger.start();\n\n// Send multi-line message to channel\nmesseger.send(\"myChannel1\", \"Hello\", \"World\");\n\n// Subscribe to channel\nmessenger.subscribe(\"myChannel1\").consume((channel, lines) -\u003e {\n    // do something\n});\n```\n\nThe subscribed message channels can have a cache instance to avoid receive outbound messages, by default it use the best available implementation.\n\n```java\nMessenger messenger = new Messenger();\n\n// Subscribe to channel\nMessageChannel channel = messenger.subscribe(\"myChannel1\").consume((channel, lines) -\u003e {\n    // do something\n});\n\n// Cache message IDs\nchannel.cache(true);\n\n// Cache with provided expiration\nchannel.cache(20, TimeUnit.SECONDS);\n```\n\nAnd also can have an end-to-end encryption.\n\n```java\nMessenger messenger = new Messenger();\n\n// Subscribe to channel\nMessageChannel channel = messenger.subscribe(\"myChannel1\").consume((channel, lines) -\u003e {\n    // do something\n});\n\n// Your key\nSecretKey key = ...;\n\nchannel.encryptor(Encryptor.of(key));\n```","funding_links":["https://github.com/sponsors/Rubenicos"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsaicone%2Fdelivery4j","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsaicone%2Fdelivery4j","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsaicone%2Fdelivery4j/lists"}