{"id":15492207,"url":"https://github.com/google/cel-java","last_synced_at":"2026-01-11T16:57:50.716Z","repository":{"id":65765811,"uuid":"587078119","full_name":"google/cel-java","owner":"google","description":"Fast, portable, non-Turing complete expression evaluation with gradual typing (Java)","archived":false,"fork":false,"pushed_at":"2025-01-07T02:24:28.000Z","size":2754,"stargazers_count":165,"open_issues_count":9,"forks_count":22,"subscribers_count":9,"default_branch":"main","last_synced_at":"2025-01-07T16:07:30.001Z","etag":null,"topics":["cel","expression","expression-language","expression-parser","java"],"latest_commit_sha":null,"homepage":"https://cel.dev","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/google.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","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}},"created_at":"2023-01-09T22:47:41.000Z","updated_at":"2025-01-07T02:24:21.000Z","dependencies_parsed_at":"2025-01-14T20:36:10.074Z","dependency_job_id":"014f1746-859a-4212-a631-8ab40de8ba58","html_url":"https://github.com/google/cel-java","commit_stats":null,"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/google%2Fcel-java","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/google%2Fcel-java/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/google%2Fcel-java/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/google%2Fcel-java/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/google","download_url":"https://codeload.github.com/google/cel-java/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":236166129,"owners_count":19105809,"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":["cel","expression","expression-language","expression-parser","java"],"created_at":"2024-10-02T07:59:35.747Z","updated_at":"2025-10-12T04:32:08.001Z","avatar_url":"https://github.com/google.png","language":"Java","readme":"# Common Expression Language for Java\n\nThe Common Expression Language (CEL) is a non-Turing complete language designed\nfor simplicity, speed, safety, and portability. CEL's C-like [syntax][1] looks\nnearly identical to equivalent expressions in C++, Go, Java, and TypeScript.\n\n```java\n// Check whether a resource name starts with a group name.\nresource.name.startsWith(\"/groups/\"+auth.claims.group)\n```\n\n```go\n// Determine whether the request is in the permitted time window.\nrequest.time - resource.age \u003c duration(\"24h\")\n```\n\n```typescript\n// Check whether all resource names in a list match a given filter.\nauth.claims.email_verified \u0026\u0026 resources.all(r, r.startsWith(auth.claims.email))\n```\n\nA CEL \"program\" is a single expression. The examples have been tagged as\n`java`, `go`, and `typescript` within the markdown to showcase the commonality\nof the syntax.\n\nCEL is ideal for lightweight expression evaluation when a fully sandboxed\nscripting language is too resource intensive.\n\n---\n\n* [Quick Start](#quick-start)\n* [Overview](#overview)\n    * [Environment Setup](#environment-setup)\n    * [Parsing](#parsing)\n    * [Checking](#checking)\n        * [Macros](#macros)\n    * [Evaluation](#evaluation)\n        * [Errors](#errors)\n    * [Extensions](#extensions)\n* [Install](#install)\n* [Common Questions](#common-questions)\n* [License](#license)\n\n---\n\n## Quick Start\n\n### Install\n\nCEL-Java is available in Maven Central Repository. [Download the JARs here][8] or add the following to your build dependencies:\n\n**Maven (pom.xml)**:\n\n```xml\n\u003cdependency\u003e\n  \u003cgroupId\u003edev.cel\u003c/groupId\u003e\n  \u003cartifactId\u003ecel\u003c/artifactId\u003e\n  \u003cversion\u003e0.11.0\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n**Gradle**\n\n```gradle\nimplementation 'dev.cel:cel:0.11.0'\n```\n\nThen run this example:\n\n```java\nimport dev.cel.common.CelAbstractSyntaxTree;\nimport dev.cel.common.CelValidationException;\nimport dev.cel.common.types.SimpleType;\nimport dev.cel.compiler.CelCompiler;\nimport dev.cel.compiler.CelCompilerFactory;\nimport dev.cel.runtime.CelEvaluationException;\nimport dev.cel.runtime.CelRuntime;\nimport dev.cel.runtime.CelRuntimeFactory;\nimport java.util.Map;\n\npublic class HelloWorld {\n  // Construct the compilation and runtime environments.\n  // These instances are immutable and thus trivially thread-safe and amenable to caching.\n  private static final CelCompiler CEL_COMPILER =\n      CelCompilerFactory.standardCelCompilerBuilder().addVar(\"my_var\", SimpleType.STRING).build();\n  private static final CelRuntime CEL_RUNTIME =\n      CelRuntimeFactory.standardCelRuntimeBuilder().build();\n\n  public void run() throws CelValidationException, CelEvaluationException {\n    // Compile the expression into an Abstract Syntax Tree.\n    CelAbstractSyntaxTree ast = CEL_COMPILER.compile(\"my_var + '!'\").getAst();\n\n    // Plan an executable program instance.\n    CelRuntime.Program program = CEL_RUNTIME.createProgram(ast);\n\n    // Evaluate the program with an input variable.\n    String result = (String) program.eval(Map.of(\"my_var\", \"Hello World\"));\n    System.out.println(result); // 'Hello World!'\n  }\n}\n```\n\n## Overview\n\nDetermine the variables and functions you want to provide to CEL. Parse and\ncheck an expression to make sure it's valid. Then evaluate the output AST\nagainst some input. Checking is optional, but strongly encouraged.\n\n### Environment Setup\n\nConfiguration for the entire CEL stack can be done all at once via the\n`CelFactory.standardCelBuilder()`, or can be composed into compilation and\nevaluation via the `CelCompilerFactory` and `CelRuntimeFactory`.\n\nThe simplest form of CEL usage is as follows:\n\n```java\nCel cel = CelFactory.standardCelBuilder().build();\n```\n\nMore commonly, your application will want to configure type-checking separately\nfrom the runtime. Use `CelCompilerFactory` to construct a compilation\nenvironment and declare the types, macros, variables, and functions to use with\nyour CEL application:\n\n```java\n// Example environment for the following expression:\n//    resource.name.startsWith('/groups/' + group)\nCelCompiler cel = CelCompilerFactory.standardCelCompilerBuilder()\n    .setStandardMacros(CelStandardMacro.HAS)\n    .setContainer(\"google.rpc.context.AttributeContext\")\n    .addMessageTypes(AttributeContext.getDescriptor())\n    .addVar(\"resource\",\n        StructTypeReference.create(\"google.rpc.context.AttributeContext.Resource\"))\n    .addVar(\"group\", SimpleType.STRING)\n    .build();\n```\n\nMore information about the features which are supported on the builder may be\nfound in the [`CelCompilerBuilder`][9].\n\n### Parsing\n\nSome CEL use cases only require parsing of an expression in order to be useful.\nFor example, one example might want to check whether the expression contains any\nnested comprehensions, or possibly to pass the parsed expression to a C++ or Go\nbinary for evaluation. Presently, Java does not support parse-only evaluation.\n\n```java\nCelValidationResult parseResult =\n    cel.parse(\"resource.name.startsWith('/groups/' + group)\");\ntry {\n  return parseResult.getAst();\n} catch (CelValidationException e) {\n  // Handle exception...\n}\n```\n\n### Checking\n\nType-checking is performed on `CelAbstractSyntaxTree` values to ensure that the\nexpression is well formed and all variable and function references are defined.\n\nType-checking can be performed immediately after parsing an expression:\n\n```java\ntry {\n  CelValidationResult parseResult =\n      cel.parse(\"resource.name.startsWith('/groups/' + group)\");\n  CelValidationResult checkResult = cel.check(parseResult.getAst());\n  return checkResult.getAst();\n} catch (CelValidationException e) {\n  // Handle exception...\n}\n```\n\nOr, the parse and type-check can be combined into the `compile` call. This is\nlikely the more common need.\n\n```java\nCelValidationResult compileResult =\n    cel.compile(\"resource.name.startsWith('/groups/' + group)\");\ntry {\n  return compileResult.getAst();\n} catch (CelValidationException e) {\n  // Handle exception...\n}\n```\n\n#### Macros\n\nMacros were introduced to support optional CEL features that might not be\ndesired in all use cases without the syntactic burden and complexity such\nfeatures might desire if they were part of the core CEL syntax. Macros are\nexpanded at parse time and their expansions are type-checked at check time.\n\nFor example, when macros are enabled it is possible to support bounded iteration\n/ fold operators. The macros `all`, `exists`, `exists_one`, `filter`, and `map`\nare particularly useful for evaluating a single predicate against list and map\nvalues.\n\n```javascript\n// Ensure all tweets are less than 140 chars\ntweets.all(t, t.size() \u003c= 140)\n```\n\nThe `has` macro is useful for unifying field presence testing logic across\nprotobuf types and dynamic (JSON-like) types.\n\n```javascript\n// Test whether the field is a non-default value if proto-based, or defined\n// in the JSON case.\nhas(message.field)\n```\n\nBoth cases traditionally require special syntax at the language level, but these\nfeatures are exposed via macros in CEL.\n\nRefer to the [CEL Specification][10] for full listings of available macros. To\nleverage them, simply set the desired macros via `setStandardMacros` on the\nbuilder:\n\n```java\nCelCompiler.standardCelBuilder()\n  .setStandardMacros(CelStandardMacro.STANDARD_MACROS)\n```\n\n### Evaluation\n\nExpressions can be evaluated using once they are type-checked/compiled by\ncreating a `CelRuntime.Program` from a `CelAbstractSyntaxTree`:\n\n```java\nCelRuntime celRuntime = CelRuntimeFactory.standardCelRuntimeBuilder().build();\ntry {\n  CelRuntime.Program program = celRuntime.createProgram(compileResult.getAst());\n  return program.eval(\n      ImmutableMap.of(\n          \"resource\", Resource.newBuilder().setName(\"/groups/\").build(),\n          \"group\", \"admin\"\n      ));\n} catch (CelEvaluationException e) {\n  // Handle evaluation exceptions ...\n}\n```\n\nThe evaluation is thread-safe and side effect free thus many different inputs can\nbe sent to the same `cel.Program`.\n\n#### Partial State\n\nIn distributed apps it is not uncommon to have edge caches and central services.\nIf possible, evaluation should happen at the edge, but it isn't always possible\nto know the full state required for all values and functions present in the CEL\nexpression.\n\nTo improve the odds of successful evaluation with partial state, CEL uses\ncommutative logical operators `\u0026\u0026`, `||`. If an error or unknown value (not the\nsame thing) is encountered on the left-hand side, the right-hand side is\nevaluated also to determine the outcome. While it is possible to implement\nevaluation with partial state without this feature, this method was chosen\nbecause it aligns with the semantics of SQL evaluation and because it's more\nrobust to evaluation against dynamic data types such as JSON inputs.\n\nIn the following truth-table, the symbols `\u003cx\u003e` and `\u003cy\u003e` represent error or\nunknown values, with the `?` indicating that the branch is not taken due to\nshort-circuiting. When the result is `\u003cx, y\u003e` this means that both the args are\npossibly relevant to the result.\n\n| Expression          | Result   |\n|---------------------|----------|\n| `false \u0026\u0026 ?`        | `false`  |\n| `true \u0026\u0026 false`     | `false`  |\n| `\u003cx\u003e \u0026\u0026 false`      | `false`  |\n| `true \u0026\u0026 true`      | `true`   |\n| `true \u0026\u0026 \u003cx\u003e`       | `\u003cx\u003e`    |\n| `\u003cx\u003e \u0026\u0026 true`       | `\u003cx\u003e`    |\n| `\u003cx\u003e \u0026\u0026 \u003cy\u003e`        | `\u003cx, y\u003e` |\n| `true \\|\\| ?`       | `true`   |\n| `false \\|\\| true`   | `true`   |\n| `\u003cx\u003e \\|\\| true`     | `true`   |\n| `false \\|\\| false`  | `false`  |\n| `false \\|\\| \u003cx\u003e`    | `\u003cx\u003e`    |\n| `\u003cx\u003e \\|\\| false`    | `\u003cx\u003e`    |\n| `\u003cx\u003e \\|\\| \u003cy\u003e`      | `\u003cx, y\u003e` |\n\n### Errors\n\nParse and check errors have friendly error messages with pointers to where the\nissues occur in source:\n\n```sh\nERROR: \u003cinput\u003e:1:40: undefined field 'undefined'\n    | TestAllTypes{single_int32: 1, undefined: 2}\n    | .......................................^`,\n```\n\nBoth the parsed and checked expressions contain source position information\nabout each node that appears in the output AST. This information can be used\nto determine error locations at evaluation time as well.\n\n### Extensions\n\nCEL-Java offers a suite of [canonical extensions][11] to support commonly\nneeded features that falls outside the CEL specification.\n\nExamples:\n\n```java\n// String manipulation\n'hello hello'.replace('he', 'we')     // returns 'wello wello'\n'hello hello hello'.split(' ')     // returns ['hello', 'hello', 'hello']\n\n// Math extensions\nmath.greatest(-42.0, -21.5, -100.0)   // -21.5\nmath.least(-42.0, -21.5, -100.0)   // -100.0\n\n// Proto extensions\nproto.getExt(msg, google.expr.proto2.test.int32_ext) // returns int value\n\n// Local bindings\ncel.bind(a, 'hello',\n    cel.bind(b, 'world', a + b + b + a)) // \"helloworldworldhello\"\n```\n\n## Common Questions\n\n### Why not JavaScript, Lua, or WASM?\n\nJavaScript and Lua are rich languages that require sandboxing to execute safely.\nSandboxing is costly and factors into the \"what will I let users evaluate?\"\nquestion heavily when the answer is anything more than O(n)\ncomplexity.\n\nCEL evaluates linearly with respect to the size of the expression and the input\nbeing evaluated when macros are disabled. The only functions beyond the\nbuilt-ins that may be invoked are provided by the host environment. While\nextension functions may be more complex, this is a choice by the application\nembedding CEL.\n\nBut, why not WASM? WASM is an excellent choice for certain applications and is\nfar superior to embedded JavaScript and Lua, but it does not have support for\ngarbage collection and non-primitive object types require semi-expensive calls\nacross modules. In most cases CEL will be faster and just as portable for its\nintended use case, though for node.js and web-based execution CEL too may offer\na WASM evaluator with direct to WASM compilation.\n\n### Do I need to Parse _and_ Check?\n\nChecking is an optional, but strongly suggested, step in CEL expression\nvalidation. It is sufficient in some cases to simply Parse and rely on the\nruntime bindings and error handling to do the right thing.\n\n### Where can I learn more about the language?\n\n* See the [CEL Spec][1] for the specification and conformance test suite.\n* Ask for support on the [CEL Java Discuss][2] Google group.\n\n### How can I contribute?\n\n* See [CONTRIBUTING.md](./CONTRIBUTING.md) to get started.\n* Use [GitHub Issues][7] to request features or report bugs.\n\n### Dependencies\n\nJava 8 or newer is required.\n\n| Library               | Details              |\n|-----------------------|----------------------|\n| [Guava][3]            | N/A                  |\n| [RE2/J][4]            | N/A                  |\n| [Protocol Buffers][5] | Full or lite runtime |\n| [ANTLR4][6]           | Java runtime         |\n\n## License\n\nReleased under the [Apache License](LICENSE).\n\n[1]:  https://github.com/google/cel-spec\n[2]:  https://groups.google.com/forum/#!forum/cel-java-discuss\n[3]:  https://github.com/google/guava\n[4]:  https://github.com/google/re2j\n[5]:  https://github.com/protocolbuffers/protobuf/tree/master/java\n[6]:  https://github.com/antlr/antlr4/tree/master/runtime/Java\n[7]:  https://github.com/google/cel-java/issues\n[8]:  https://search.maven.org/search?q=g:dev.cel\n[9]:  https://github.com/google/cel-java/blob/main/compiler/src/main/java/dev/cel/compiler/CelCompilerBuilder.java\n[10]:  https://github.com/google/cel-spec/blob/master/doc/langdef.md#macros\n[11]:  https://github.com/google/cel-java/blob/main/extensions/src/main/java/dev/cel/extensions/README.md\n","funding_links":[],"categories":["Table of Contents","\u003ca name=\"Java\"\u003e\u003c/a\u003eJava"],"sub_categories":["Packages"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgoogle%2Fcel-java","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgoogle%2Fcel-java","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgoogle%2Fcel-java/lists"}