{"id":20134632,"url":"https://github.com/twcable/jackalope","last_synced_at":"2025-04-09T17:22:03.035Z","repository":{"id":28117834,"uuid":"31616751","full_name":"TWCable/jackalope","owner":"TWCable","description":"An in-memory implementation of the JCR with stubbing capabilities for Apache Sling","archived":false,"fork":false,"pushed_at":"2016-10-28T22:10:14.000Z","size":351,"stargazers_count":19,"open_issues_count":11,"forks_count":6,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-03-23T19:22:33.578Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/TWCable.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-03-03T19:25:18.000Z","updated_at":"2022-05-03T18:50:10.000Z","dependencies_parsed_at":"2022-07-25T17:52:37.281Z","dependency_job_id":null,"html_url":"https://github.com/TWCable/jackalope","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TWCable%2Fjackalope","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TWCable%2Fjackalope/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TWCable%2Fjackalope/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TWCable%2Fjackalope/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/TWCable","download_url":"https://codeload.github.com/TWCable/jackalope/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248075147,"owners_count":21043531,"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":[],"created_at":"2024-11-13T21:10:34.627Z","updated_at":"2025-04-09T17:22:03.013Z","avatar_url":"https://github.com/TWCable.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"![Jackalope](jackalope.png)\n\n[![Build Status](https://travis-ci.org/TWCable/jackalope.svg?branch=master)](https://travis-ci.org/TWCable/jackalope)\n\n[ ![Download](https://api.bintray.com/packages/twcable/aem/jackalope/images/download.svg) ](https://bintray.com/twcable/aem/jackalope/_latestVersion)\n\n## PURPOSE\n\nJackalope is an in-memory implementation of the JCR with stubbing capabilities for Apache Sling.\n\nThe goal of Jackalope is to better enable unit testing JCR representations of complex objects structures.\nJava objects can normally be simply represented in the JCR as nodes with properties.\n\nSimple mocking of the underlying JCR and Sling interfaces *can* be used to unit test reading and writing\nthese kinds of objects. However, when object aggregations like Sling component structures need to be\nrepresented, the inability of simple mock objects to manage state become a real limitation.\n\nThe obvious solution is to use a JCR implementation that uses memory as its storage. There are, in fact, memory-based JCR implementations -- including one that is distributed with the Jackrabbit project. (Jackrabbit is the reference implementation for the JCR JSR.) All of these, however, require far too much in setup and resources to be useful for unit testing. They are designed to be long running, multi-threaded processes.\n\nOur solution to this problem is to develop a simple and fast JCR implementation that can be used in unit tests.\nIt does not implement the complete JCR spec, but just the parts that we've needed, including the basic facilities for reading and writing repository workspaces.\n\nThere is another great project from [Citytech called Prosper](https://github.com/Citytechinc/prosper), which was released after Jackalope was written internally at Time Warner Cable. Each project has its own set of features, but the *primary* difference between Jackalope and Prosper is that Prosper uses Groovy string-based metaprogramming for building its trees, which has all the advantages and disadvantages of a fully dynamic API. Choose the one that best your needs/style: Choice is good. :-)\n\n\n## Versions\n\nThe 3.x line targets AEM 6.x, whereas the 2.x versions target AEM 5.6.\n\nVersioning follows the [Semantic Versioning standard](http://semver.org/)\n\n## Packages\n\nThe library is composed of 3 main packages.\n\n### Builder (com.twcable.jackalope)\n\nThis is the primary interface that should be used by clients of the library.\nThe `JCRBuilder` class contains factory methods that can be used to create a virtual repository for use in test cases.\n\nTo bring this class's methods in, typically you would do:\n```groovy\nimport static JCRBuilder.repostory\nimport static JCRBuilder.node\nimport static JCRBuilder.property\n```\n\n### Sling Implementation (com.twcable.jackalope.sling)\n\nThis package contains the classes that implement the primary Sling API classes like `Resource` and `ResourceResolver`.\nUsers may want to use `SimpleResourceResolverFactory` to inject into services and servlets.\n\n### JCR Implementation (com.twcable.jackalope.jcr)\n\nThis package contains the classes that implement the primary JCR API classes like `Node` and `Property`.\n\n## Examples\n\n### Building and using a partial repository\n\n```groovy\ngiven:\ndef repository = repository(\n    node(\"content\",\n        node(\"test1\",\n            node(\"callingrates\",\n                node(\"intl-direct-dial\",\n                    property(\"sling:resourceType\", \"admin/components/content/callingratetable\"),\n                    node(\"france\",\n                        property(\"sling:resourceType\", \"admin/components/content/callingrate\"),\n                        property(\"additional-minute-rate\", \"0.60\"))))))).build()\ndef resolver = new SimpleResourceResolverFactory(repository).administrativeResourceResolver\ndef resource = resolver.getResource(\"/content/test1/callingrates/intl-direct-dial\")\n\nwhen:\ndef callingRateTable = new CallingRateTable(resource)\n\nthen:\ncallingRateTable.getRate(\"france\")\ncallingRateTable.getRate(\"france\").additionalMinuteRate == \"0.60\"\n```\n\nThe resource resolver factory can be used to test servlets and services by injection.\n\n```groovy\ndef repository = repository(\n    node(\"content\",\n        node(\"test1\",\n            node(\"callingrates\",\n                node(\"intl-direct-dial\",\n                    property(\"sling:resourceType\", \"admin/components/content/callingratetable\"),\n                    node(\"france\",\n                        property(\"sling:resourceType\", \"admin/components/content/callingrate\"),\n                        property(\"additional-minute-rate\", \"0.60\"))))))).build()\ndef servlet = new CallingRatesImportServlet(new SimpleResourceResolverFactory(repository))\n```\n\n### Building and using a node tree\n\nSome classes are designed to read and write node trees and do not require the full repository\nimplementation.  These classes can build and use nodes directly.\n\n```groovy\ndef node = node(\"content\",\n               node(\"test1\",\n                   node(\"callingrates\",\n                       node(\"intl-direct-dial\",\n                           property(\"sling:resourceType\", \"admin/components/content/callingratetable\"),\n                           node(\"france\",\n                               property(\"sling:resourceType\", \"admin/components/content/callingrate\"),\n                               property(\"additional-minute-rate\", \"0.60\"))))))).build()\n```\n\n### Returning a query result\n\nQueries are also supported.  A JCRQueryBuilder is used to create a query manager that associates queries\nwith fixed result sets that can be used for testing.\n\n```groovy\ndef node = node(\"result\").build()\nJCRQueryBuilder.queryManager(node.session, query(\"query\", \"language\", result(node))).build()\n\nwhen:\ndef queryResult = node.session.workspace.queryManager.createQuery(\"query\", \"language\").execute()\n\nthen:\nqueryResult.nodes.hasNext()\n\nwhen:\ndef results = Lists.newArrayList(queryResult.nodes)\n\nthen:\nresults[0] == node\n```\n\n## BUILDING\n\nJackalope uses gradle as its build system:\n\n`./gradlew build`\n\n# Including In Your Build\n\n[ ![Download](https://api.bintray.com/packages/twcable/aem/jackalope/images/download.svg) ](https://bintray.com/twcable/aem/jackalope/_latestVersion)\n\nJackalope can be used by including the following in your\nbuild files (assuming Gradle):\n\n```groovy\nrepositories {\n  maven {\n    url \"http://dl.bintray.com/twcable/aem\"\n  }\n}\n\ntestCompile 'com.twcable.jackalope:jackalope:3.0.2'\n```\n\n# Releasing\n\nFor the developers of Jackalope, please read [the documentation for creating and releasing a new version](docs/RELEASING.adoc).\n\n# LICENSE\n\nCopyright 2015 Time Warner Cable, Inc.\n\nLicensed under the Apache License, Version 2.0 (the \"License\"); you may not use this file except in compliance\nwith the License. You may obtain a copy of the License at\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under the License is distributed on\nan \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for\nthe specific language governing permissions and limitations under the License.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftwcable%2Fjackalope","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftwcable%2Fjackalope","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftwcable%2Fjackalope/lists"}