{"id":51002371,"url":"https://github.com/faltfe/rulify","last_synced_at":"2026-06-20T16:02:47.521Z","repository":{"id":46245284,"uuid":"352916474","full_name":"faltfe/rulify","owner":"faltfe","description":"Simple package that help to run defined rules","archived":false,"fork":false,"pushed_at":"2026-06-02T13:04:26.000Z","size":330,"stargazers_count":0,"open_issues_count":8,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-06-02T14:27:16.512Z","etag":null,"topics":["java"],"latest_commit_sha":null,"homepage":"https://faltfe.github.io/rulify/","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/faltfe.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","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}},"created_at":"2021-03-30T07:52:44.000Z","updated_at":"2026-06-02T13:04:24.000Z","dependencies_parsed_at":"2023-02-09T16:30:19.576Z","dependency_job_id":null,"html_url":"https://github.com/faltfe/rulify","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/faltfe/rulify","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/faltfe%2Frulify","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/faltfe%2Frulify/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/faltfe%2Frulify/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/faltfe%2Frulify/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/faltfe","download_url":"https://codeload.github.com/faltfe/rulify/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/faltfe%2Frulify/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34576054,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-20T02:00:06.407Z","response_time":98,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["java"],"created_at":"2026-06-20T16:02:46.744Z","updated_at":"2026-06-20T16:02:47.510Z","avatar_url":"https://github.com/faltfe.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# rulify\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![codecov](https://codecov.io/gh/faltfe/rulify/branch/main/graph/badge.svg?token=8KSNJFNNFU)](https://codecov.io/gh/faltfe/rulify)\n[![Build, run tests and create coverage](https://github.com/faltfe/rulify/actions/workflows/build-test-coverage.yml/badge.svg)](https://github.com/faltfe/rulify/actions/workflows/build-test-coverage.yml)\n\n## What is rulify? 🤔\n\nSome time ago I had the challenge of mapping a some business rules into code. I\nwas not satisfied with existing libraries because they were either to complex\nand had to many features or the implementation was not intuitiv for me. That was\nthe birth of _rulify_.\n\n_rulify_ itself is a library that provides a framework for implementing\nbusiness rules as code. A rule is an abstract representation of exactly one\ncondition, which is followed by an action. In other words, a rule describes\nan _if-then_ structure.\n\nThe special feature of _rulify_ is that both conditions and actions can be\ncreated independently of the rule, so that they can be reused several times in\ndifferent rules.\n\n**‼ The library does not claim to fulfil the criteria of a rule engine,\nnor to replace it. ‼**\n\n## How _rulify_ works? 🔨\n\nWhen working with Maven import the dependency\n\n```xml\n\n\u003cdependency\u003e\n    \u003cgroupId\u003eio.github.faltfe\u003c/groupId\u003e\n    \u003cartifactId\u003erulify-api\u003c/artifactId\u003e\n    \u003cversion\u003e1.0.0\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n_rulify_ offers two classes which can be used as a start for the implementation\nof a rule.\n\n1. A `Rule` will evaluate a `Condition` and perform the provided `Action`\n2. An `Effect` will evaluate a `Condition`, modify the data with the given\n   `Modifier` and run lastly the provided `Action`.\n\n![rulify-api-uml](assets/rulify-api-uml.png)\n\nA `Rule` or `Effect` always works with data provided by your own implementation.\nThis data must be managed by a single object, which is ideally a POJO.\n\n---\n\n\u003cp style=\"text-align: center;\"\u003e\n    \u003ca href=\"https://faltfe.github.io/rulify/\" target=\"_blank\"\u003e\n        🛑 \u003cstrong\u003eFor more information read the detail documentation.\u003c/strong\u003e 🛑\n    \u003c/a\u003e\n\u003c/p\u003e\n\n---\n\n## How to get started with _rulify_? 🎆\n\nAll you need is a POJO and a custom implementation of a `Rule` or a `Effect`\nand implement the mandatory methods. Let's say there is our POJO `Cat` that\nlooks like\n\n```java\npublic class Cat {\n\n    // Setter and Getter omitted for simplicity\n    private String name = \"Meow 🐱\";\n    private boolean cute;\n\n    public Cat(boolean isCute) {\n        this.cute = isCute;\n    }\n\n    public boolean isCute() {\n        return cute;\n    }\n\n    public void purr() {\n        System.out.println(\"🐈 + \", name);\n    }\n}\n```\n\nNow we need your `CatRule` which will evaluate a business rule and execute a\ndefined action.\n\n```java\npublic class CatRule extends Rule\u003cCat\u003e {\n\n    @Override\n    public Cat data() { // \u003c- provide an object to work with\n        return new Cat(true);\n    }\n\n    @Override\n    public Condition\u003cCat\u003e condition() { // \u003c- this is our business rule\n        return Cat::isCute; // -\u003e uses object provided at data()\n    }\n\n    @Override\n    public Action\u003cCat\u003e action() { // \u003c- what should happen\n        return Cat::purr; // -\u003e prints \"🐈 Meow 🐱\"\n    }\n}\n```\n\nThe last part is to execute the `Rule`.\n\n```java\npublic class MyRuleExecutor() {\n\n    public static void main(String[] args) {\n        Executable rule = new CatRule();\n        rule.execute();\n    }\n}\n```\n\nIf the data should be manipulated or a side effect is needed replace\n`Rule\u003cCat\u003e` with `Effect\u003cCat\u003e`. The image below shows the different flows\nbetween a `Rule` and an `Effect`.\n\n![rulify-rule-effect-flow](assets/rulify-rule-effect-flow.drawio.png)\n\n## What are the benefits of _rulify_?\n\nThe first and main advantage of this library compared to what actually? In my\nopinion, there two groups to which _rulify_ can be compared.\n\n### Benefits compared to plain If-Then implementations\n\nAt first glance, using rulify seems significantly more complicated than an\nIf-Else-Then construct. For simple conditions it is true, but as soon as things\nget more complex, the strengths of rulify come to the fore.\n\n1. A rule is reusable.\n2. There is a separation between the components condition and execution. It\n   is easy to implement SOLID this way.\n3. The individual components are easier to test.\n\n### Benefits compared to any rule engine\n\nAs mentioned before a rule engine is much more complex than this library\nbecause _rulify_ aims another target. The main target is to provide a better\nmechanism for If-Then conditions.\n\n---\n\n## Rulify runner 🏃‍♂️🏃‍♀️\n\nThe _rulify_ runner is an extension build on top of the _rulify_ API. There\nare different implementations based on the target environment:\n\n- Java SE\n- Java EE (`java.javax`)\n- Jakarta (`java.jakarta`)\n- Spring Boot\n\n### How to start with rulify runner?\n\n_rulify runner_ provides an API with the interface `RulifyRunner` that has the\nmethod `run()`. Each implementation for a specific platform should implement\nthis method. Depending on the target system, select the right dependency.\n\n![rulify-runner](assets/package-view.drawio.png)\n\nIndependent on selected implementation there are the following steps required:\n\n1. Create a custom `Rule` or `Effect` and annotate the class the rule or\n   effect is working on with `@Rule(MyRule.class)`.\n\n    An implementation of the `Executable` interface would also be valid if a\n    rule or effect is not required.\n\n2. Get a valid reference to `RulifyRunner` and execute the `run()` method.\n\n#### Example implementation for Java standalone projects\n\nImport the required dependency. There is no need to import `rulify-api`\nbecause it is a transitive dependency.\n\n```xml\n\n\u003cdependency\u003e\n    \u003cgroupId\u003eio.github.faltfe\u003c/groupId\u003e\n    \u003cartifactId\u003erulify-runner-standalone\u003c/artifactId\u003e\n    \u003cversion\u003e1.0.0\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nSample implementation\n\n```java\npublic class RuleScanner {\n\n    public static void main(String[] args) {\n        RulifyRunner runner = new RuleRunner(\"io.github.faltfe.rulify\");\n        runner.run();\n    }\n}\n```\n\n#### Example for Jakarta CDI\n\nImport the required dependency. There is no need to import `rulify-api`\nbecause it is a transitive dependency.\n\n```xml\n\n\u003cdependency\u003e\n    \u003cgroupId\u003eio.github.faltfe\u003c/groupId\u003e\n    \u003cartifactId\u003erulify-runner-jakarta\u003c/artifactId\u003e\n    \u003cversion\u003e1.0.0\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nIt is recommended that a `RulifyRunner` instance lives as long as the\napplication is running to prevent scanning multiple times.\n\n```java\n\n@Singleton\npublic class RuleScanner {\n\n    @Inject\n    @RulifyConfig(path = \"io.github.faltfe.rulify\")\n    private RulifyRunner runner;\n\n    @PostConstruct\n    public void init() {\n        runner.run();\n    }\n}\n```\n\n#### Example for Spring Boot 3 projects\n\nImport the required dependency. There is no need to import `rulify-api`\nbecause it is a transitive dependency.\n\n```xml\n\n\u003cdependency\u003e\n    \u003cgroupId\u003eio.github.faltfe\u003c/groupId\u003e\n    \u003cartifactId\u003erulify-spring-boot3-starter\u003c/artifactId\u003e\n    \u003cversion\u003e1.0.0\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nThe configuration of the scanned packages is done inside the\n`application.properties` by setting `io.github.faltfe.rulify.path=io.github.faltfe.rulify`.\n\n```java\n\n@SpringBootApplication\npublic class Main implements CommandLineRunner {\n\n    @Autowired\n    private RulifyRunner runner;\n\n    public static void main(String[] args) {\n        SpringApplication.run(Main.class, args);\n    }\n\n    @Override\n    public void run(String... args) {\n        runner.run();\n    }\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffaltfe%2Frulify","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffaltfe%2Frulify","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffaltfe%2Frulify/lists"}