{"id":37020911,"url":"https://github.com/rogerkeays/novdl","last_synced_at":"2026-01-14T02:27:05.328Z","repository":{"id":57715009,"uuid":"53278475","full_name":"rogerkeays/novdl","owner":"rogerkeays","description":"Write your JSF views in pure Java.","archived":false,"fork":false,"pushed_at":"2023-07-13T09:51:33.000Z","size":120,"stargazers_count":4,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-08-17T19:31:45.709Z","etag":null,"topics":["java","jsf","jsf2"],"latest_commit_sha":null,"homepage":"https://rogerkeays.com/novdl","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/rogerkeays.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":null,"support":null}},"created_at":"2016-03-06T22:00:55.000Z","updated_at":"2024-12-09T19:54:09.000Z","dependencies_parsed_at":"2022-09-02T22:01:22.879Z","dependency_job_id":null,"html_url":"https://github.com/rogerkeays/novdl","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/rogerkeays/novdl","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rogerkeays%2Fnovdl","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rogerkeays%2Fnovdl/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rogerkeays%2Fnovdl/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rogerkeays%2Fnovdl/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rogerkeays","download_url":"https://codeload.github.com/rogerkeays/novdl/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rogerkeays%2Fnovdl/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28408711,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T01:52:23.358Z","status":"online","status_checked_at":"2026-01-14T02:00:06.678Z","response_time":107,"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","jsf","jsf2"],"created_at":"2026-01-14T02:27:04.644Z","updated_at":"2026-01-14T02:27:05.322Z","avatar_url":"https://github.com/rogerkeays.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n# NoVDL: Write your JSF views in pure Java\n\nNoVDL is a View Description Language that makes your JSF views more robust by\nimplementing them in Java. By using Java to write your views you automatically\ngain many features.\n\n- type safety\n- compile-time code verification\n- stack traces that actually make sense\n- ide autocomplete support\n- ide refactoring support\n- java static methods for composite components\n- java function composition for decorating views\n- java inheritance for decorating views\n- java object references to access components\n- java method references to invoke action listeners\n- java namespacing for component libraries\n- high performance\n- less reliance on flaky EL expressions\n- less reliance on managed beans\n- no XML configuration, taglibs, or magic annotations\n- one language to learn instead of three (Java + XML + EL)\n\n## Example View\n\n    public class OrderForm extends BasePage implements Activity {\n\n        @Override\n        public void buildView(FacesContext faces, UIViewRoot root) {\n            List\u003cProduct\u003e products = ProductDAO.getAllProducts();\n            UIPanelGroup main = \n              h_panelGroup().children(\n                f_verbatim(\"\u003ch1\u003eOrder Form\u003c/h1\u003e\"),\n                h_form().id(\"order\").children(\n                  h_dataTable().id(\"products\").value(products).var(\"product\").width(\"100%\").children(\n                    h_column().header(f_verbatim(\"Description\")).children(\n                      h_outputLink().id(\"link\").valuex(\"${product.page.linkURL}\").children(\n                        h_outputText().valuex(\"${product.description}\")\n                      )\n                    ),\n                    h_column()\n                        .header(f_verbatim(\"Quantity\"))\n                        .children(h_inputText().id(\"quantity\").converter(new IntegerConverter())\n                        .footer(h_commandButton().id(\"submit\").value(\"Create Order\")\n                                        .actionListener(createOrder()))\n                    )\n                  )\n                )\n              );\n\n\n            /*\n             * If your master template is implemented in java you'll create a \n             * separate function to build it, e.g.\n             *\n             * build_master_view(faces, root, main);\n             *\n             * NoVDL also includes a function to execute a facelet which can \n             * then include the partial view you created here using a \n             * binding=\"..\" attribute.\n             */\n            build_from_facelet(faces, root, getMasterTemplate());\n        }\n    }\n\n## Mapping Routes\n\nThe current implementation maps the view id to its Java implementation by\nconverting the url path to a class name. E.g.\n\n    http://localhost/com/example/Demo.xhtml\n\nis routed to the class\n\n    com.example.Demo\n    \nIf you need different functionality, you could rewrite get_view_class_name()\nand recompile NoVDL. If there is enough demand, I'll make this function\nconfigurable.\n\n## Value Expressions\n\nNoVDL allows value expressions to be set by using the setter method which ends\nin *x*. e.g.\n\n    h_outputText().value(\"Hello World\"); // or\n    h_outputText().valuex(\"${bean.greeting}\");\n\nThis was chosen partly because the NoVDL components are automatically generated\nfrom the JSF API, and partly because EL is discouraged in NoVDL. Ideally, we'd\nlike to be able to implement ValueExpressions using lambda functions.\n\n## Composite Components with a Static Factory\n\nIt is very easy to make composite components using a static factory method. \n\n    public static UIPanel create_data_grid(Data current) {\n        HPanelGrid grid = h_panelGrid().id(\"ox_related\").columns(4);\n        for (Match match : data.getMatches()) {\n            HPanelGroup panel = h_panelGroup().id(\"ox_related_\" + match.getId());\n            if (match.getThumbnail() != null) {\n                panel.children(\n                    h_outputLink().value(match.getLinkURL()).children(\n                        h_graphicImage().value(match.getThumbnail())\n                    )\n                );\n            }\n            panel.children(\n                f_verbatim(\"\u003cp\u003e\"),\n                h_outputLink().value(match.getLinkURL()).children(\n                    h_outputText().value(match.getTitle())\n                ),\n                f_verbatim(\"\u003c/p\u003e\")\n            );\n            grid.getChildren().add(panel);\n        }\n        return grid;\n    }\n\nThis is a good example of why XML is a questionable choice for user interfaces.\nIs it declarative code or is it procedural? Actually, it's a mixture, and there\nis not much advantage to declarative languages when you start to mix in\nprocedural (or functional) code.\n\n## Decorating Views using Functions\n\nSame idea as above. e.g.\n\n    public static void decorate_view(FacesContext faces, UIViewRoot root,\n            UIHead head, UIComponent content) {\n        root.getChildren().add(head);\n        root.getChildren().add(\n            h_body().children(\n                content\n            );\n    }\n\n## Decorating Views using Inheritance\n\nFunction composition is preferred over inheritance. If you like inheritance,\nall you need to do is make an abstract superclass that defines the sections of\nyour view. e.g.\n\n    public abstract class MasterView implements Activity {\n\n        @Override\n        public void buildView(FacesContext faces, UIViewRoot root) {\n            root.getChildren().add(build_head(faces));\n            root.getChildren().add(\n                h_body().children(\n                    build_content(faces)\n                );\n        }\n\n        public abstract UIHead build_head(FacesContext faces);\n        public abstract UIComponent build_content(FacesContext faces);\n    }\n\n## Mixing Facelets and Java Views\n\nUse the function\n\n    build_from_facelet(faces, root, template);\n\nto execute a Facelet from your buildView function. Inside that template,\nyou'll have to reference the components you built using NoVDL. e.g.\n \n    \u003cui:decorate xmlns=\"http://www.w3.org/1999/xhtml\"\n                 xmlns:ui=\"http://java.sun.com/jsf/facelets\"\n                 xmlns:f=\"http://java.sun.com/jsf/core\"\n                 xmlns:h=\"http://java.sun.com/jsf/html\"\n                 xmlns:n=\"http://www.ninthavenue.com.au/novdl\"\n                 template=\"/master.xhtml\"\u003e\n  \n       \u003c!-- datagrid is prebuilt with NoVDL --\u003e\n       \u003ch2\u003eCurrent Data\u003c/h2\u003e\n       \u003cn:attach component=\"${bean.your_factory_method_here()}\"/\u003e\n    \u003c/ui:decorate\u003e\n\n## Editing Views on the Fly\n\nFacelets lets you edit views on the fly without recompiling or restarting the\napplication. You should be able to use [HotSwapAgent](http://www.hotswapagent.org/)\nor JRebel to achieve the same thing with NoVDL.\n\n## Installation\n\nNoVDL is automatically detected when you add the following dependency. View\nIDs that cannot be mapped to Java implementations will fall back on the default\nview decoration language (normally Facelets).\n\n    \u003cdependency\u003e\n      \u003cgroupId\u003eau.com.ninthavenue.jamaica.faces\u003c/groupId\u003e\n      \u003cartifactId\u003enovdl\u003c/artifactId\u003e\n      \u003cpackaging\u003ejar\u003c/packaging\u003e\n      \u003cversion\u003e1.0\u003c/version\u003e\n    \u003c/dependency\u003e\n\nNote: NoVDL requires Java 8.\n\n## Articles about NoVDL\n\n[NoVDL: Write your JSF views in pure Java](https://rogerkeays.com/novdl-write-your-jsf-views-in-pure-java)\n\n## Get the Source\n\nhttps://github.com/rogerkeays/novdl\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frogerkeays%2Fnovdl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frogerkeays%2Fnovdl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frogerkeays%2Fnovdl/lists"}