ShrinkWrap

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
apiorg.jboss.shrinkwrap:shrinkwrap-apiDevelopment In Use
buildorg.jboss.shrinkwrap:shrinkwrap-buildDevelopment In Use
extension-glassfishorg.jboss.shrinkwrap:shrinkwrap-extension-glassfishPrototyping
extension-jettyorg.jboss.shrinkwrap:shrinkwrap-extension-jettyPrototyping
impl-baseorg.jboss.shrinkwrap:shrinkwrap-impl-baseDevelopment In Use
spiorg.jboss.shrinkwrap:shrinkwrap-spiDevelopment In Use
doc/referenceorg.jboss.shrinkwrap:shrinkwrap-reference-guideDevelopment In Use

 

 

Project Information
Main Project Pagehttp://jboss.org/shrinkwrap
Obtaining BinariesShrinkWrap | Downloads And Maven2 Configuration
Anonymous SCMgit://github.com/shrinkwrap/shrinkwrap.git
Committer SCMgit@github.com:shrinkwrap/shrinkwrap.git
Issue Trackinghttps://jira.jboss.org/jira/browse/SHRINKWRAP
Releases Repohttps://repository.jboss.org/nexus/content/groups/public/org/jboss/shrinkwrap/
API Documentationhttp://docs.jboss.org/shrinkwrap
User Forumhttp://community.jboss.org/en/shrinkwrap
Development Forumhttp://community.jboss.org/en/shrinkwrap/dev
Development Instructions

ShrinkWrap | Development and Contribution

Release ProcessShrinkWrap | Release Process
Release PlanningShrinkWrap | Release Planning
Artworkhttp://www.jboss.org/files/jbosslabs/design/shrinkwrap/index.htm
Continuous Integrationhttp://hudson.jboss.org/hudson/job/ShrinkWrap/
Project LeadAndrew Rubinger
ContributorsJohn Bailey

Aslak Knutsen

 

Release Plan
0.1.xRetiredPrototyping and Development Series
1.0.0-alpha-xIn ProcessEarly-access Release Series used primarily for testing integration and gathering community input
1.0.0-beta-xShort-termCandidate for Frozen APIs, feature-complete
1.0.0-cr-xShort-termRelease Candidates; APIs Frozen
1.0.0FuturePromoted from re-tag of a release candidate; Stable
1.0.xFutureIncremental Patch Releases; no API changes, backwards-compatible
1.x.yUnscheduledNew feature; backwards-compatibility preserved
2.0.0-alpha-xUnscheduledOverhaul, 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

 

shrinkwrap_api.png

 

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)
  • 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

 

shrinkwrap_containers.png

 

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)

shrinkwrap_jar.png

 

Enterprise Archive (EAR)

 

shrinkwrap_ear.png

 

Web Archive (WAR)

 

shrinkwrap_war.png

 

Related