{"id":15043762,"url":"https://github.com/forge/core","last_synced_at":"2025-05-15T23:03:51.376Z","repository":{"id":542630,"uuid":"1660918","full_name":"forge/core","owner":"forge","description":"Forge Core Framework APIs and Implementation","archived":false,"fork":false,"pushed_at":"2023-03-12T00:47:35.000Z","size":36637,"stargazers_count":199,"open_issues_count":3,"forks_count":162,"subscribers_count":23,"default_branch":"master","last_synced_at":"2025-04-08T10:15:12.018Z","etag":null,"topics":["ide","java","javaee","jboss","productivity","productivity-booster"],"latest_commit_sha":null,"homepage":"http://forge.jboss.org/","language":"Java","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"epl-1.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/forge.png","metadata":{"files":{"readme":"README.asciidoc","changelog":null,"contributing":"CONTRIBUTING.asciidoc","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}},"created_at":"2011-04-25T17:55:40.000Z","updated_at":"2025-03-15T11:25:37.000Z","dependencies_parsed_at":"2023-07-06T13:01:49.661Z","dependency_job_id":null,"html_url":"https://github.com/forge/core","commit_stats":{"total_commits":5661,"total_committers":92,"mean_commits":61.53260869565217,"dds":"0.46687864334923157","last_synced_commit":"ab9e146691617029861b4be59e01a83df682e7e4"},"previous_names":[],"tags_count":141,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/forge%2Fcore","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/forge%2Fcore/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/forge%2Fcore/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/forge%2Fcore/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/forge","download_url":"https://codeload.github.com/forge/core/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254436944,"owners_count":22070946,"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":["ide","java","javaee","jboss","productivity","productivity-booster"],"created_at":"2024-09-24T20:49:33.847Z","updated_at":"2025-05-15T23:03:51.261Z","avatar_url":"https://github.com/forge.png","language":"Java","readme":"image::http://design.jboss.org/jbossforge/logo/final/jbossforge_logo_600px.png[]\n\nThe fastest way to build applications, share your software, and enjoy doing it.\n\nimage:https://github.com/forge/core/workflows/GitHub%20CI/badge.svg[\"Actions Status\", link=\"https://github.com/forge/core/actions\"]\nimage:https://img.shields.io/github/license/forge/core.svg[\"License\", link=\"https://www.eclipse.org/legal/epl-v10.html\"]\nimage:https://maven-badges.herokuapp.com/maven-central/org.jboss.forge/forge-distribution/badge.svg[\"Maven Central\", link=\"https://maven-badges.herokuapp.com/maven-central/org.jboss.forge/forge-distribution\"] \nimage:https://kiwiirc.com/buttons/irc.freenode.net/forge.png[\"Visit our IRC channel\", link=\"https://kiwiirc.com/client/irc.freenode.net/#forge\"] \n\nWhat's new and noteworthy?\n--------------------------\n\n- *JDK 11*: Forge 3 now runs on JDK 11 as its minimum requirement. Hello lambdas!\n\n- *Unix-like option names*: The shell option names are now more unix-like: Eg: `--targetPackage` is now `--target-package`.\n\n== Download Forge 3:\nJBoss Forge is packaged inside your favorite IDE plugin and also as a standalone ZIP file. They are independent of each other.\n\n- Eclipse - http://tools.jboss.org/\n- IntelliJ IDEA - http://plugins.jetbrains.com/plugin/7515\n- NetBeans - http://plugins.netbeans.org/plugin/57296/\n- Command line tools\n\n=== Get Started with the Command line tools:\n\nGetting started with the command line tools is easy:\n\n* Download a distribution\n.. Download link:https://oss.sonatype.org/service/local/artifact/maven/redirect?r=releases\u0026g=org.jboss.forge\u0026a=forge-distribution\u0026v=LATEST\u0026e=zip\u0026c=offline[JBoss Forge - Offline (Recommended)]\n... This ZIP contains the Forge runtime + Core Addons\n.. Download link:https://oss.sonatype.org/service/local/artifact/maven/redirect?r=releases\u0026g=org.jboss.forge\u0026a=forge-distribution\u0026v=LATEST\u0026e=zip[JBoss Forge - No Addons]\n... This ZIP contains the Forge runtime only\n\n* Extract the ZIP to a directory and navigate to forge-distribution-VERSION/bin directory\n* Execute forge by running\n[source,cmd]\n----\n    forge\n----\n\n\nForge is now ready to go.\n\n==== Install addons (not needed if using the offline zip)\n\nInstall the required addons by running the following commands:\n\n[source,cmd]\n----\n    forge --install groupId:artifactId,version\n----\n\n- Forge will install the required dependencies for each addon.\n\nIMPORTANT: Make sure your *settings.xml* is properly configured to use the Maven central repository or, if you wish to use a SNAPSHOT version from a core addon, the JBoss Nexus Repository, otherwise the installation will fail.\nInstructions on how to setup your *settings.xml* can be found on https://community.jboss.org/wiki/MavenGettingStarted-Developers\n\nIf you wish to install the core addons including the shell, \"Project: New\", the \"Java EE\" commands, and all other provided functionality, you should run the following command:\n\n[source,cmd]\n----\n    forge --install core\n----\n\nIf you only wish to install the Forge 2 Shell based on link:http://aeshell.github.io/[Aesh], run the following command instead:\n\n[source,cmd]\n----\n    forge --install shell\n----\n\nIf you wish to remove any addon, you can use the following command:\n\n[source,cmd]\n----\n    forge --remove groupId:artifactId,version\n----\n\n== Get Started with the Eclipse Plugin:\n\n____\nForge 3 is known to work with Eclipse Mars (Eclipse 4.5) or higher versions. Older versions of Eclipse are not supported.\n____\n\n- Install the **JBoss Tools Usage Reporting** plugin, available in http://download.jboss.org/jbosstools/updates/development/mars/ and restart Eclipse\n- Install the Forge Eclipse Plugin from http://download.jboss.org/jbosstools/mars/snapshots/updates// and restart Eclipse\n\nThis plugin starts the Forge Container and your installed addons, so you can use them directly in your workspace\n\n- Press Ctrl + 4 to show the installed addons that you may interact with (these addons use the UI addon, hence providing a user interface - see Developing an UI Addon for more details).\n\n== Available addons\n\n[options=\"header\"]\n|===\n|Addon name |Included in Eclipse Plugin ?\n\n|link:addon-manager/README.asciidoc[Addon Manager]\n|yes\n\n|link:addons/README.asciidoc[Addons]\n|yes\n\n|link:configuration/README.asciidoc[Configuration]\n|yes\n\n|link:convert/README.asciidoc[Convert]\n|yes\n\n|link:dependencies/README.asciidoc[Dependencies]\n|yes\n\n|link:dev-tools-java/README.asciidoc[Dev Tools - Java]\n|yes\n\n|link:environment/README.asciidoc[Environment]\n|yes\n\n|link:facets/README.asciidoc[Facets]\n|yes\n\n|link:git/README.asciidoc[Git]\n|yes\n\n|link:javaee/README.asciidoc[Java EE]\n|yes\n\n|link:maven/README.asciidoc[Maven]\n|yes\n\n|link:parser-java/README.asciidoc[Parser Java]\n|yes\n\n|link:parser-json/README.asciidoc[Parser Json]\n|yes\n\n|link:parser-xml/README.asciidoc[Parser XML]\n|yes\n\n|link:projects/README.asciidoc[Projects]\n|yes\n\n|link:resources/README.asciidoc[Resources]\n|yes\n\n|link:scaffold/README.asciidoc[Scaffold]\n|yes\n\n|link:shell/README.asciidoc[Shell]\n|yes\n\n|link:templates/README.asciidoc[Templates]\n|yes\n\n|link:text/README.asciidoc[Text]\n|yes\n\n|link:ui/README.asciidoc[User Interface (UI)]\n|yes\n\n|===\n\n== Developing an Addon\n\nForge addons are simple Maven projects with a special classifier \"forge-addon\". This classifier is used while installing an addon so the Furnace container can calculate its dependencies, freeing you from http://robjsoftware.org/2007/07/13/classloader-hell/[Classloader hell].\n\nOne of the most important things to know about developing a Forge addon, is that the Furnace runtime container (the core of Forge),\nis actually an embeddable, modular Java container. This means that each addon has its own `ClassLoader` and that\naddons share classes from each other, in addition to supplying their own local classes. Furnace builds a graph of\naddon dependencies at runtime, and automatically calculates which addons should see classes from other addons.\n\nFor now, however, just treat your first addon as if it were any other Java project. The differences between a \"modular\" and\n\"traditional\" environment are not as great as you might think, and the Furnace development model has been created in\na way that should make these differences seem natural, almost transparent.\n\n=== Create a Maven project\n\nForge Addons must be JARs published with a 'forge-addon' classifier. Add this plugin configuration to your pom.xml:\n\n[source,xml]\n----\n\u003cbuild\u003e\n   \u003cplugins\u003e\n      \u003cplugin\u003e\n         \u003cgroupId\u003eorg.apache.maven.plugins\u003c/groupId\u003e\n         \u003cartifactId\u003emaven-jar-plugin\u003c/artifactId\u003e\n         \u003cexecutions\u003e\n            \u003cexecution\u003e\n               \u003cid\u003ecreate-forge-addon\u003c/id\u003e\n               \u003cphase\u003epackage\u003c/phase\u003e\n               \u003cgoals\u003e\n                  \u003cgoal\u003ejar\u003c/goal\u003e\n               \u003c/goals\u003e\n               \u003cinherited\u003efalse\u003c/inherited\u003e\n               \u003cconfiguration\u003e\n                  \u003cclassifier\u003eforge-addon\u003c/classifier\u003e\n               \u003c/configuration\u003e\n            \u003c/execution\u003e\n         \u003c/executions\u003e\n      \u003c/plugin\u003e\n   \u003c/plugins\u003e\n\u003c/build\u003e\n----\n\nIn order to use CDI and services from other addons in your addon, you'll need to reference the Furnace CDI container addon as a dependency your _pom.xml_ file:\n\n[source,xml]\n----\n\u003cdependency\u003e\n   \u003cgroupId\u003eorg.jboss.forge.furnace.container\u003c/groupId\u003e\n   \u003cartifactId\u003ecdi\u003c/artifactId\u003e\n   \u003cclassifier\u003eforge-addon\u003c/classifier\u003e\n   \u003cscope\u003eprovided\u003c/scope\u003e\n\u003c/dependency\u003e\n----\n\nCAUTION: Addon dependencies *MUST* be declared in the Maven pom.xml that produces your `forge-addon` classified artifact; otherwise, Furnace will *NOT* use this dependency as a `forge-addon`. Instead, addon dependencies declared via transitive dependencies will be included as local JAR files and re-bundled with your addon. More than likely, re-bundling a `forge-addon` in your Addon is *NOT* what you want.\n\nYour complete POM should now look something like this:\n\n[source,xml]\n----\n\u003cproject xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\"\u003e\n   \u003cmodelVersion\u003e4.0.0\u003c/modelVersion\u003e\n\n   \u003cgroupId\u003ecom.example\u003c/groupId\u003e\n   \u003cartifactId\u003eexample\u003c/artifactId\u003e\n   \u003cversion\u003e1.0.0-SNAPSHOT\u003c/version\u003e\n\n   \u003cname\u003eMy First Addon\u003c/name\u003e\n   \n   \u003cproperties\u003e\n        \u003cversion.forge\u003e3.5.1.Final\u003c/version.forge\u003e\n   \u003c/properties\u003e\n   \n   \u003cdependencyManagement\u003e\n        \u003cdependencies\u003e\n            \u003cdependency\u003e\n                \u003cgroupId\u003eorg.jboss.forge\u003c/groupId\u003e\n                \u003cartifactId\u003eforge-bom\u003c/artifactId\u003e\n                \u003cversion\u003e${version.forge}\u003c/version\u003e\n                \u003ctype\u003epom\u003c/type\u003e\n                \u003cscope\u003eimport\u003c/scope\u003e\n            \u003c/dependency\u003e\n        \u003c/dependencies\u003e\n    \u003c/dependencyManagement\u003e\n\n   \u003cdependencies\u003e\n      \u003cdependency\u003e\n         \u003cgroupId\u003eorg.jboss.forge.furnace.container\u003c/groupId\u003e\n         \u003cartifactId\u003ecdi\u003c/artifactId\u003e\n         \u003cclassifier\u003eforge-addon\u003c/classifier\u003e\n         \u003cscope\u003eprovided\u003c/scope\u003e\n      \u003c/dependency\u003e\n   \u003c/dependencies\u003e\n\n   \u003cbuild\u003e\n      \u003cplugins\u003e\n         \u003cplugin\u003e\n            \u003cgroupId\u003eorg.apache.maven.plugins\u003c/groupId\u003e\n            \u003cartifactId\u003emaven-jar-plugin\u003c/artifactId\u003e\n            \u003cexecutions\u003e\n               \u003cexecution\u003e\n                  \u003cid\u003ecreate-forge-addon\u003c/id\u003e\n                  \u003cphase\u003epackage\u003c/phase\u003e\n                  \u003cgoals\u003e\n                     \u003cgoal\u003ejar\u003c/goal\u003e\n                  \u003c/goals\u003e\n                  \u003cinherited\u003efalse\u003c/inherited\u003e\n                  \u003cconfiguration\u003e\n                     \u003cclassifier\u003eforge-addon\u003c/classifier\u003e\n                  \u003c/configuration\u003e\n               \u003c/execution\u003e\n            \u003c/executions\u003e\n         \u003c/plugin\u003e\n      \u003c/plugins\u003e\n   \u003c/build\u003e\n\u003c/project\u003e\n----\n\n=== Add behavior to your addon\n\nA service is implemented as a POJO (Plain Old Java Object):\n\n[source,java]\n----\npublic class ExampleServiceImpl\n{\n   public String doSomething() {\n        // Do stuff...\n   }\n}\n----\n\nHowever, best practices favor creating a service interface, otherwise consumers will be required to request your specific service implementation. For example:\n\n[source,java]\n----\npublic interface ExampleService\n{\n   public String doSomething();\n}\n----\n\nThen simply implement the service interface:\n\n[source,java]\n----\npublic class ExampleServiceImpl implements ExampleService\n{\n   public String doSomething() {\n        // Do stuff...\n   }\n}\n----\n\n=== Re-use functionality from other addons:\n\nForge has a modular architecture that enables you to re-use functionality from other addons, directly in your own addon code. In order to achieve this, you must add addon-dependencies in your `pom.xml` file.\n\n[source,xml]\n----\n\u003cproject\u003e\n   ...\n\n   \u003cdependencies\u003e\n      \u003c!-- Addon Dependencies --\u003e\n      \u003cdependency\u003e\n         \u003cgroupId\u003eorg.jboss.forge.addon\u003c/groupId\u003e\n         \u003cartifactId\u003eresources\u003c/artifactId\u003e\n         \u003cclassifier\u003eforge-addon\u003c/classifier\u003e\n         \u003cscope\u003eprovided\u003c/scope\u003e\n      \u003c/dependency\u003e\n      \u003cdependency\u003e\n         \u003cgroupId\u003eorg.jboss.forge.addon\u003c/groupId\u003e\n         \u003cartifactId\u003eui\u003c/artifactId\u003e\n         \u003cclassifier\u003eforge-addon\u003c/classifier\u003e\n         \u003cscope\u003eprovided\u003c/scope\u003e\n      \u003c/dependency\u003e\n\n      \u003c!-- Furnace Container --\u003e\n      \u003cdependency\u003e\n         \u003cgroupId\u003eorg.jboss.forge.furnace.container\u003c/groupId\u003e\n         \u003cartifactId\u003ecdi\u003c/artifactId\u003e\n         \u003cclassifier\u003eforge-addon\u003c/classifier\u003e\n         \u003cscope\u003eprovided\u003c/scope\u003e\n      \u003c/dependency\u003e\n   \u003c/dependencies\u003e\n\n   ...\n\u003c/project\u003e\n----\n\n==== What scope should my addon dependencies be?\n\nThere is a simple rule that will make this an easy decision:\n\n____\n\"``compile`` if everyone knows, `provided` if I know, `runtime` if nobody knows.\"\n____\n\nTo explain, if you never publicly expose types (classes, interfaces, etc...) from another addon in the outward-facing APIs of your addon, then you should include\nthat addon as `provided` scope. If you do, however, expose classes from that addon in the public APIs of your code,\nthen that addon should be labeled as `compile` scope (default,) which means that this dependency will be *'exported'*\nto consumers that depend on your addon.\n\nAddon dependencies may also be made `optional` if consumers of your addon should be able to choose whether or not\ncertain functionality is enabled, or if your addon behaves differently when other addons are already deployed to the\ncontainer.\n\nThe following chart explains this in detail. Assume that our addon depends on the `resources` addon, which provides\nthe `ResourceFactory` and `FileResource` classes:\n\n[cols=\"1a,2,3\", options=\"header\"]\n|===\n|Example |Scope should be |Explanation\n\n|\nThe `Resource\u003c?\u003e` and `ResourceFactory` types are provided by the `resources` addon. Your addon defines `InternalExample`.\n[source,java]\n----\npublic class InternalExample {\n   @Inject private ResourceFactory factory;\n\n   public void doSomething(File file) {\n      Resource\u003c?\u003e r = factory.create(file);\n      System.out.println(\"New resource: \" + r)a\n   }\n}\n----\n|`provided`\n|Consumers of your addon never see classes or interfaces from the resources addon; it is only used internally as an\nimplementation detail and is not exposed in your public API. \n\n*Your addon should depend on the resources addon at `provided` scope.*\n\n|\nThe `Resource\u003c?\u003e` and `ResourceFactory` types are provided by the `resources` addon. Your addon defines `ExposedExample`.\n[source,java]\n---- \npublic class ExposedExample {\n   @Inject private ResourceFactory factory;\n\n   public Resource\u003c?\u003e doSomething(File file) {\n      Resource\u003c?\u003e r = factory.create(file);\n      return r;\n   }\n}\n----\n|`compile`\n|Consumers of your addon require classes from the `resources` addon to interact with your code, since it has been referenced in the your addon's public API. \n\n*Your addon should depend on the resources addon at `compile` scope.*\n\n\n|\nThe type `LockCreator` is defined by addon X.\n[source,java]\n----\npublic class LockCreator {\n   public void createFile(\n      @Observes PostStartup event)\n   {\n      File lock = new File(\"lockfile\");\n      lock.createNewFile();\n   }\n}\n----\n\nYour addon defines `LockConsumer`, which requires that a file \"lockfile\" be available when it runs. This file is created by addon X.\n[source,java]\n----\npublic class LockConsumer {\n   public void deleteLock() {\n      File lock = new File(\"lockfile\");\n      Assert.assertTrue(lock.exists());\n   }\n}\n----\n|`runtime`\n|Your addon makes assumptions about the runtime environment that are satisfied by the presence of addon X, but your addon does not depend on or expose types from addon X in its APIs.\n\n*Your addon should include addon X at `runtime` scope.*\n\n|\nThe type `Logger` is defined by addon X, but addon X does not include an implementation of its own logging interface.\n[source,java]\n----\npublic interface Logger {\n   public void log(String message)\n}\n----\n\nYour addon defines `LoggerConsumer`, which depends on addon X in order to use `Logger`, but requires that another addon (addon Y) actually provide an logging implementation.\n[source,java]\n----\npublic class LoggerConsumer {\n   @Inject private Imported\u003cLogger\u003e loggers;\n\n   public void logEverything() {\n      for( Logger log : loggers {\n         log.log(\"Log for you!\");\n      }\n   }\n}\n----\n|`provided` / `runtime`\n|Your addon requires instances of `Logger`, which is defined in addon X, but provided by addon Y (for instance), thus your addon requires addon Y to provide an instance of `Logger`, but does not need to import or compile against addon Y's types directly (they are provided by Furnace). Your addon does not expose the `Logger` type from addon X in its APIs.\n\n*Your addon should include addon X at `provided` scope, and addon Y at `runtime` scope.*\n|===\n\n\n\n=== Test your addon\n\nOne of the most important concepts of writing a Forge addon is writing tests using the Furnace test harness. This\nallows you to test your code in an actual Furnace environment, and verify that things are behaving as expected. Typically\nwe suggest using a separate project to test your addon in order to keep concerns separate, which tends to lead to cleaner\ncode and fewer surprises.\n\nFor simplicity's sake, we'll assume that your addon uses the default Furnace container (`org.jboss.forge.furnace.container:cdi`).\n\n==== Set up the test-harness in your build descriptor (pom.xml)\n\nAdd the following dependencies to your pom.xml file if they are not already there. Make sure that the Furnace versions\nare the same as the rest of your project.\n\n[source,xml]\n----\n\u003cdependency\u003e\n   \u003cgroupId\u003eorg.jboss.forge.furnace.test\u003c/groupId\u003e\n   \u003cartifactId\u003efurnace-test-harness\u003c/artifactId\u003e\n   \u003cversion\u003eFURNACE_VERSION\u003c/version\u003e\n   \u003cscope\u003etest\u003c/scope\u003e\n\u003c/dependency\u003e\n\u003cdependency\u003e\n   \u003cgroupId\u003eorg.jboss.forge.furnace.test\u003c/groupId\u003e\n   \u003cartifactId\u003earquillian-furnace-classpath\u003c/artifactId\u003e\n   \u003cversion\u003eFURNACE_VERSION\u003c/version\u003e\n   \u003cscope\u003etest\u003c/scope\u003e\n\u003c/dependency\u003e\n----\n\nIf you are writing tests in a separate project or sub-project, you should also add a dependency to your addon, or\nto the addon you wish to test (you can test anything you like.)\n\n[source,xml]\n----\n\u003cdependency\u003e\n   \u003cgroupId\u003ecom.example\u003c/groupId\u003e\n   \u003cartifactId\u003eexample\u003c/artifactId\u003e\n   \u003cclassifier\u003eforge-addon\u003c/classifier\u003e\n   \u003cversion\u003eYOUR_VERSION\u003c/version\u003e\n   \u003cscope\u003etest\u003c/scope\u003e\n\u003c/dependency\u003e\n----\n\n==== Write your first test\n\nNow, you'll need to create a test class with the following layout, using the standard JUnit test APIs:\n\n[source,java]\n----\npackage org.example;\n\nimport org.jboss.arquillian.container.test.api.Deployment;\nimport org.jboss.arquillian.junit.Arquillian;\nimport org.jboss.forge.arquillian.archive.AddonArchive;\nimport org.jboss.shrinkwrap.api.ShrinkWrap;\nimport org.junit.Assert;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\n@RunWith(Arquillian.class)\npublic class ExampleFurnaceTest {\n\n   @Deployment\n   public static AddonArchive getDeployment() {\n      AddonArchive archive = ShrinkWrap.create(AddonArchive.class);\n      return archive;\n   }\n\n   @Test\n   public void testSomething() throws Exception {\n      Assert.fail(\"Not implemented\");\n   }\n}\n----\n\nThen you'll need to add some configuration so that your addon will be deployed to the test environment. This is done\nusing the `@AddonDeployment` annotation. You'll also need to add an addon dependency link from your test case\nto your addon (otherwise the test case will not be able to use any of your addon's classes or services.)\n\n[source,java]\n----\n@RunWith(Arquillian.class)\npublic class ExampleFurnaceTest {\n\n   @Deployment\n   @AddonDeployments({\n       @AddonDeployment(name = \"org.example:example\", version = \"YOUR_VERSION\")\n   })\n   public static AddonArchive getDeployment() {\n      AddonArchive archive = ShrinkWrap.create(AddonArchive.class)\n         .addBeansXML()\n         .addAsAddonDependencies(\n            AddonDependencyEntry.create(\"org.example:example\", \"YOUR_VERSION\"),\n         );\n      return archive;\n   }\n\n   @Test\n   public void testSomething() throws Exception {\n      Assert.fail(\"Not implemented\");\n   }\n}\n----\n\nNOTE: The `@AddonDeployment` annotation is used to specify addons that must be deployed before the Addon-Under-Test is deployed in Furnace. The `AddonDependencyEntry.create(...)` method is used to specify addons that the Addon-Under-Test depends on.\nYou can use the `@AddonDependency` annotation if you want to deploy AND make your Addon-Under-Test dependent on the specified addon. By using the `@AddonDependency` annotation you no longer need to specify `AddonDependencyEntry.create(...)` in your `AddonArchive`.\n\nNow that the test case deploys and depends on your addon, you may access services from it via injection:\n\n[source,java]\n----\n@RunWith(Arquillian.class)\npublic class ExampleFurnaceTest {\n\n   @Deployment\n   @AddonDeployments({\n       @AddonDeployment(name = \"org.example:example\", version = \"YOUR_VERSION\")\n   })\n   public static AddonArchive getDeployment() {\n      AddonArchive archive = ShrinkWrap.create(AddonArchive.class)\n         .addBeansXML()\n         .addAsAddonDependencies(\n            AddonDependencyEntry.create(\"org.example:example\", \"YOUR_VERSION\"),\n         );\n      return archive;\n   }\n\n   @Inject\n   private ExampleService service;\n\n   @Test\n   public void testSomething() throws Exception {\n      Assert.assertNotNull(service);\n      Assert.assertNotNull(service.doSomething());\n   }\n}\n----\n\nThis is the basic premise of using the test-harness. For detailed examples, take a\nhttps://github.com/forge/core/tree/master/resources/tests/src/test/java/org/jboss/forge/addon/resource[look at some of the existing\nForge test cases] in our github repository.\n\nNOTE: The `version` parameter in `@AddonDependency` and in the `AddonDependencyEntry.create(...)` method are optional. By not specifying them means that the test harness\nwill attempt to find the version based on the tests' build descriptor (pom.xml). In this case, if the dependent addon is not present in the tests' build descriptor, the test execution should fail.\n\n\n=== Install your addon in the local maven repository:\n\nDepending on the Forge environment in which you are running, installation steps will differ.\n\nFor Eclipse:: Open the Forge quick-assist menu, select either \"Build and install an Addon\" or \"Install an addon\" to build and install your project, or install a pre-built maven artifact.\n\nFor the Shell::\n\n\n[source,cmd]\n----\n    mvn clean install\n----\n\nRun\n\n[source,cmd]\n----\n    ./forge --install yourgroupId:artifactId,version\n----\n\nWARNING: This coordinate is *NOT* the same as Maven's. You MUST use a comma (,) between the `artifactId` and the version.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fforge%2Fcore","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fforge%2Fcore","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fforge%2Fcore/lists"}