class Buildr::Packaging::Java::EarTask

Extend the JarTask to create an EAR file.

The following component types are supported by the EARTask:

  • :war – A J2EE Web Application

  • :ejb – An Enterprise Java Bean

  • :jar – A J2EE Application Client.

  • :lib – An ear scoped shared library (for things like logging,

    spring, etc) common to the ear components

The EarTask uses the "Mechanism 2: Bundled Optional Classes" as described on [2]. All specified libraries are added to the EAR archive and the Class-Path manifiest entry is modified for each EAR component. Special care is taken with WebApplications, as they can contain libraries on their WEB-INF/lib directory, libraries already included in a war file are not referenced by the Class-Path entry of the war in order to avoid class collisions

EarTask supports all the same options as JarTask, in additon to these two options:

  • :display_name – The displayname to for this ear on application.xml

  • :map – A Hash used to map component type to paths within the EAR.

    By default each component type is mapped to a directory with the same name,
    for example, EJBs are stored in the /ejb path. To customize:
     package(:ear).map[:war] = 'web-applications'
     package(:ear).map[:lib] = nil # store shared libraries on root of archive

EAR components are added by means of the #add, #<<, #push methods Component type is determined from the artifact's type.

package(:ear) << project('coolWebService').package(:war)

The << method is just an alias for push, with the later you can add multiple components at the same time. For example..

package(:ear).push 'org.springframework:spring:jar:2.6',
 projects('reflectUtils', 'springUtils'),
 project('coolerWebService').package(:war)

The add method takes a single component with an optional hash. You can use it to override some component attributes.

You can override the component type for a particular artifact. The following example shows how you can tell the EarTask to treat a JAR file as an EJB:

# will add an ejb entry for the-cool-ejb-2.5.jar in application.xml
package(:ear).add 'org.coolguys:the-cool-ejb:jar:2.5', :type=>:ejb
# A better syntax for this is:
package(:ear).add :ejb=>'org.coolguys:the-cool-ejb:jar:2.5'

By default, every JAR package is assumed to be a library component, so you need to specify the type when including an EJB (:ejb) or Application Client JAR (:jar).

For WebApplications (:war)s, you can customize the context-root that appears in application.xml. The following example also specifies a different directory inside the EAR where to store the webapp.

package(:ear).add project(:remoteService).package(:war),
 :path=>'web-services', :context_root=>'/Some/URL/Path'
1

java.sun.com/j2ee/sdk_1.2.1/techdocs/guides/ejb/html/Overview5.html#10106

2

java.sun.com/j2ee/verified/packaging.html

Constants

SUPPORTED_TYPES

Attributes

description[RW]

The description entry for application.xml

dirs[RW]

Map from component type to path inside the EAR.

display_name[RW]

The display-name entry for application.xml

security_roles[RW]

Security roles entry for application.xml

Public Class Methods

new(*args) click to toggle source
Calls superclass method
# File lib/buildr/java/packaging.rb, line 395
def initialize(*args)
 super
 @dirs = Hash.new { |h, k| k.to_s }
 @libs, @components, @security_roles = [], [], []
 prepare do
 @components.each do |component|
 path(component[:path]).include(component[:clone] || component[:artifact])
 end
 path('META-INF').include(descriptor)
 end
end

Public Instance Methods

<<(*args)
Alias for: push
add(*args) click to toggle source

Add an artifact to this EAR.

# File lib/buildr/java/packaging.rb, line 408
def add(*args)
 options = Hash === args.last ? args.pop.clone : {}
 args.flatten!
 args.map! do |pkg|
 case pkg
 when Project
 pkg.packages.select { |pp| JarTask === pp && SUPPORTED_TYPES.include?(pp.type) }
 when Rake::FileTask
 pkg # add the explicitly provided file
 when Hash
 Buildr.artifact(pkg)
 when String
 begin
 Buildr.artifact(pkg)
 rescue # not an artifact spec, it must me a filename
 file(pkg)
 end
 else
 raise "Invalid EAR component #{pkg.class}: #{pkg}"
 end
 end
 args.flatten!
 args.compact!
 if args.empty?
 raise ":type must not be specified for type=>component argument style" if options.key?(:type)
 raise ":as must not be specified for type=>component argument style" if options.key?(:as)
 comps = {}
 options.delete_if { |k, v| comps[k] = v if SUPPORTED_TYPES.include?(k) }
 raise "You must specify at least one valid component to add" if comps.empty?
 comps.each { |k, v| add(v, {:as => k}.merge(options)) }
 else
 args.each do |artifact|
 type = options[:as] || options[:type]
 unless type
 type = artifact.respond_to?(:type) ? artifact.type : artifact.to_s.pathmap('%x').to_sym
 type = :lib if type == :jar
 end
 raise "Unknown EAR component type: #{type}. Perhaps you may explicity tell what component type to use." unless
 SUPPORTED_TYPES.include?(type)
 component = options.merge(:artifact => artifact, :type => type,
 :id=>artifact.respond_to?(:to_spec) ? artifact.id : artifact.to_s.pathmap('%n'),
 :path=>options[:path] || dirs[type].to_s)
 component[:clone] = component_clone(component) unless :lib == type
 # update_classpath(component) unless :lib == type || Artifact === artifact
 @components << component
 end
 end
 self
end
Also aliased as: push
push(*args)
Also aliased as: <<
Alias for: add

Protected Instance Methods

associate(project) click to toggle source
# File lib/buildr/java/packaging.rb, line 480
def associate(project)
 @project = project
end
component_clone(component) click to toggle source
# File lib/buildr/java/packaging.rb, line 463
def component_clone(component)
 file(path_to(component[:path], component[:artifact].to_s.pathmap('%f')) => component[:artifact]) do |task|
 mkpath task.to_s.pathmap('%d')
 cp component[:artifact].to_s, task.to_s
 Manifest.update_manifest(task) do |manifest|
 class_path = manifest.main['Class-Path'].to_s.split
 included_libs = class_path.map { |fn| fn.pathmap('%f') }
 Zip::File.foreach(task.to_s) do |entry|
 included_libs << entry.name.pathmap('%f') if entry.file? && entry.name =~ /^WEB-INF\/lib\/[^\/]+$/
 end
 # Include all other libraries in the classpath.
 class_path += libs_classpath(component).reject { |path| included_libs.include?(File.basename(path)) }
 manifest.main['Class-Path'] = class_path.join(' ')
 end
 end
end
update_classpath(component) click to toggle source
# File lib/buildr/java/packaging.rb, line 489
def update_classpath(component)
 package = file(component[:artifact].to_s)
 package.manifest = (package.manifest || {}).dup # avoid mofifying parent projects manifest
 package.prepare do
 header = case package.manifest
 when Hash then package.manifest
 when Array then package.manifest.first
 end
 if header
 # Determine which libraries are already included.
 class_path = header['Class-Path'].to_s.split
 included_libs = class_path.map { |fn| File.basename(fn) }
 included_libs += package.path('WEB-INF/lib').sources.map { |fn| File.basename(fn) }
 # Include all other libraries in the classpath.
 class_path += libs_classpath(component).reject { |path| included_libs.include?(File.basename(path)) }
 header['Class-Path'] = class_path.join(' ')
 end
 end
end