Skip the Build!
Shrinkwrap provides a simple API to assemble archives like JARs, WARs, and EARs in Java.
Introduction
Packaging specifications such as Java Archives (JAR) and Enterprise Archives (EAR) are standard mechanisms for declaring a collection of Classes and resources into one unit. Often these are intended to be run directly or deployed into a web or application server. Archives carry with them implicit metadata regarding their structure, from which concerns like ClassLoading scope and manifest parameters may be inferred.
However useful, archives typically require the addition of a build step within the development lifecycle, either via a script or extra tool. The ShrinkWrap project provides a simple API to programmatically assemble archives in code, optionally allowing for export into ZIP or Exploded File formats. This makes it very fast to prototype "virtual" archives from resources scattered about the classpath, the filesystem or remote URLs.
Modules
Module Name | Maven2 ID | Status |
---|---|---|
api | org.jboss.shrinkwrap:shrinkwrap-api | Development In Use |
build | org.jboss.shrinkwrap:shrinkwrap-build | Development In Use |
extension-glassfish | org.jboss.shrinkwrap:shrinkwrap-extension-glassfish | Prototyping |
extension-jetty | org.jboss.shrinkwrap:shrinkwrap-extension-jetty | Prototyping |
impl-base | org.jboss.shrinkwrap:shrinkwrap-impl-base | Development In Use |
spi | org.jboss.shrinkwrap:shrinkwrap-spi | Development In Use |
doc/reference | org.jboss.shrinkwrap:shrinkwrap-reference-guide | Development In Use |
Project Information
Main Project Page | http://jboss.org/shrinkwrap |
Obtaining Binaries | ShrinkWrap | Downloads And Maven2 Configuration |
Anonymous SCM | git://github.com/shrinkwrap/shrinkwrap.git |
Committer SCM | git@github.com:shrinkwrap/shrinkwrap.git |
Issue Tracking | https://jira.jboss.org/jira/browse/SHRINKWRAP |
Releases Repo | https://repository.jboss.org/nexus/content/groups/public/org/jboss/shrinkwrap/ |
API Documentation | http://docs.jboss.org/shrinkwrap |
User Forum | http://community.jboss.org/en/shrinkwrap |
Development Forum | http://community.jboss.org/en/shrinkwrap/dev |
Development Instructions | |
Release Process | ShrinkWrap | Release Process |
Release Planning | ShrinkWrap | Release Planning |
Artwork | http://www.jboss.org/files/jbosslabs/design/shrinkwrap/index.htm |
Continuous Integration | http://hudson.jboss.org/hudson/job/ShrinkWrap/ |
Project Lead | alrubinger |
Contributors | johnbailey |
Release Plan
0.1.x | Retired | Prototyping and Development Series |
1.0.0-alpha-x | In Process | Early-access Release Series used primarily for testing integration and gathering community input |
1.0.0-beta-x | Short-term | Candidate for Frozen APIs, feature-complete |
1.0.0-cr-x | Short-term | Release Candidates; APIs Frozen |
1.0.0 | Future | Promoted from re-tag of a release candidate; Stable |
1.0.x | Future | Incremental Patch Releases; no API changes, backwards-compatible |
1.x.y | Unscheduled | New feature; backwards-compatibility preserved |
2.0.0-alpha-x | Unscheduled | Overhaul, refactoring. Features may be added/dropped, API contract disappears |
Sample Code
Make an EJB3 JAR from Classes visible from the Thread Context ClassLoader
// Make a name for the JAR String name = "slsb.jar"; // Create and add classes to the JAR JavaArchive archive = ShrinkWrap.create(JavaArchive.class, name) .addClasses(OutputBean.class, OutputLocalBusiness.class);
Log out the full contents of an archive in "ls -l" form (useful for debugging)
Archive<?> archive = null; // Assume we have one archive.toString(true); // Verbose flag /* Will make output: slsb.jar: /org/jboss/embedded/testsuite/fulldep/ejb3/slsb/OutputLocalBusiness.class /org/jboss/embedded/testsuite/fulldep/ejb3/slsb/OutputBean.class */
Add a ClassLoader resource, assigning it a specific location (Path) within the Archive
JavaArchive archive = ShrinkWrap.create(JavaArchive.class, "archive.jar"); Path pathToMetaInf = Paths.create("META-INF"); Path pathToEjbJar = Paths.create(pathToMetaInf,"ejb-jar.xml"); // Could also have done Paths.create("META-INF/ejb-jar.xml") archive.addResource("resources/myEjbJar.xml", pathToEjbJar);
Make a simple WAR with webapp descriptor, a Servlet, and a JSP
final Class<?> servletClass = JspForwardingServlet.class; final WebArchive archive = ShrinkWrap.create(WebArchive.class, name); archive.setWebXML(PATH_ACTUAL_WEB_XML) .addResource(PATH_JSP) .addClass(servletClass);
Write an Archive to the Filesystem in ZIP encoding (JAR/EAR/WAR, etc)
// Export to the Filesystem as a real JAR InputStream zipStream = archive.as(ZipExporter.class).exportZip(); // Get a FileOutputStream and then write the contents of "zipStream" to it
Write an Archive as exploded form to the Filesystem
File destinationDir = null; // Directory to which we'll export archive.as(ExplodedExporter.class).exportExploded(destinationDir);
Read an Archive from the Filesystem in ZIP encoding (JAR/EAR/WAR, etc)
ZipFile existingZipFile = .. // Import from the Filesystem as a real JAR JavaArchive archive = ShrinkWrap.create(ZipImporter.class, "archive.jar") .importZip(existingZipFile) .as(JavaArchive.class);
Read an Archive from a exploded directory on the Filesystem
File sourceDir = null; // Directory from which we'll import archive.as(ExplodedImporter.class).importExploded(sourceDir);
Deploy an Archive directly to a Deployable Container (ie. JBoss Embedded)
JBossASEmbeddedServer server = null; // From somewhere Archive<?> archive = null; // From somewhere server.deploy(archive); // Do some testing, then undeploy server.undeploy(archive);
API Guide
There are two main entry points to the ShrinkWrap api:
- ShrinkWrap
- Main entry point into the ShrinkWrap system. Provides shortcut mechanism to create Archives of different type under a default Domain.
- ArchivePaths
- A common factory for creating ArchivePath objects
Generically speaking,the central types in the ShrinkWrap are:
- Archive
- A Collection of resources (Assets), each with its own naming context / filename (ArchivePath)
- Asset
- A generic resource, collection of bytes
- This term is used instead of "Resource" because "Resource" may be used in some contexts to mean "ClassLoader resource"
- ArchivePath
- Name/location within an archive under which an asset may be stored
- Assignable
- general interface for representing entities such as Archives as different extension types
In practice, it's actually more convenient to support the addition of some contrete types like ClassLoader resources, URLs, or Classes than by adding Assets themselves. To handle this there are archive extensions targeted for these uses, called "Containers".
- ClassContainer
- Supports addition of classes and packages
- EnterpriseContainer
- Supports addition of:
- application.xml
- Application Resources
- Whole modules (other archives)
- Supports addition of:
- LibraryContainer
- Supports addition of libraries
- ManifestContainer
- Supports addition of META-INF/MANIFEST.MF and manifest resources under META-INF
- ResourceContainer
- Supports addition of ClassLoader resources
- WebContainer
- Supports addition of:
- WEB-INF/web.xml
- WEB-INF resources
- Supports addition of:
From these container extensions we may compose into specification extensions. These will be the types used most frequently from an end-user perspective.
JavaArchive (JAR)
Enterprise Archive (EAR)
Web Archive (WAR)