In this webinar, we touch on:
- Polyglot support: Ruby, Groovy, and Scala DSLs. These have all been actively worked on in the recent past, especially the Ruby and Scala DSLs.
- Full incremental support: the complete Maven lifecycle including an incremental command line compiler based on JDT, all with m2e integration
- Aggressive parallelization: a new parallelization mode that also optimizes scheduling based on critical path analysis
- Generations: a new form of continuous delivery for Maven -- Smart delta protocol and no more SNAPHOTs!
- Shell: long-lived CLI process for Maven
Much of this work is functional, and the new parallelization mode and generations support are actively being used in production. We are still iterating on these specific features but they show a lot of promise. Where all of this code eventually lands is a question for the Maven development community. All of this work was developed outside of Apache, and how easy it is to integrate back into the Maven project remains to be seen. At the very least there is a lot of very interesting work and we wanted to start the dialog because Maven just isn't going to die :).
3. It’s too hard for organizations
to efficiently deliver
JVM-based software
4. The problem with delivery
What is an application and how do you reason about it? Why you might be here today?
External Services
Internal Components
3rd Party Components
Configuration
Machine
v1.0
5. Software Delivery Chain
Developer checks code into the SCM
IDE
Developer requests components
from Repoman and the components
are delivered to the developer
2
CI checks code out of the SCM
SCM
CI
3
CI instructs build tool to
perform a build
4
1
Repository
Central
Build
5
Build tool deploys components
to repository manager
Provisioning system requests components
and configuration from Nexus.
6
Provisioner
7
Agent
Provisioning system provisions apps and
components to the agents
managing runtimes
Agent
Agent
8. Incremental build
We’ve supported incremental build in m2eclipse for quite a while
‣
‣
‣
‣
m2eclipse is capable of operating on a single resource with a single Mojo call -- very efficient
We implemented incremental build for Maven on the CLI
We implemented a custom Guice scope for Maven’s core to @Inject what we call a BuildContext
We Implemented versions the Mojos for the standard lifecycle including and incremental CLI compiler based
on Eclipse JDT
9. public class BuildAvoidanceDemo {
private final BuildContext context;
private final File inputDir;
private final File outputDir;
private final Set<String> includes;
private final Set<String> excludes;
//
//
//
//
//
//
performed automatically by the framework
1.
2.
3.
4.
delete all stale or orphaned output files produced during previous build(s)
persist BuildContext state such that it can be used during the next build
replay any messages not cleared from previous build(s)
raise build error if any of the inputs processed in this or previous builds had SEVERITY_ERROR message
@Inject
public BuildAvoidanceDemo(BuildContext context, File inputDir, Set<String> includes, Set<String> excludes, File outputDir) {
this.context = context;
this.inputDir = inputDir;
this.includes = includes;
this.excludes = excludes;
this.outputDir = outputDir;
}
public void execute() throws IOException {
// determine all input files, regardless of their up-to-date status
// in this particular case use basedir with ant-style includes/excludes patterns
FileSet inputs = new FileSetBuilder(inputDir).addIncludes(includes).addExcludes(excludes).build();
// context.registerInputs registers specified inputs FileSets with the build context, which is necessary to
// enable cleanup of stale outputs. it returns collection of input files that require processing
for (File inputFile : context.registerInputs(inputs)) {
// context.addProcessedInput marks beginning of processing of the input file
// it clears all output files and messages associated with the input file for this build
context.addProcessedInput(inputFile);
// mapping between input and output files is outside of scope of BuildContext API
File outputFile = determineOuputFile(outputDir, inputFile);
// context.newOutputStream associates input and output files, which is necessary to determine input files
// that require processing and to perform cleanup of stale output files.
OutputStream os = context.newOutputStream(inputFile, outputFile);
try {
// generation of output file contents is outside of scope of BuildContext API
// likewise, Message object, if any, is application specific and is not part of BuildContext API
Collection<Message> messages = generateOutput(inputFile, os);
}
}
}
// record error and warning messages generated during input file processing
for (Message message : messages) {
context.addMessage(inputFile, message.getLine(), message.getColumn(), message.getText(), BuildContext.SEVERITY_ERROR, null);
}
} finally {
os.close();
}
17. SCM
SCM
SCM
SCM
revision 100:branch X
revision 101:branch X
revision 102:branch X
revision 103:branch X
Generation 100
Generation 101
Generation 102
Generation 103
As time passes and your product gets better (I hope)
18. Workspaces
How does a workspace relate to a generation?
provisio-webserver
javax.inject
jetty-server
javax.servlet
jetty-continuation
jetty-http
jetty-io
jetty-util
jetty-webapp
jetty-xml
jetty-util
jetty-deploy
jetty-webapp
jetty-util
jetty-jmx
jetty-util
jetty-util
19. What if generations were supported across the delivery chain?
IDE
2
SCM
CI
3
4
1
Consuming a new generation
Repository
Build
5
Producing a new generation
6
Provisioner
7
Agent
Agent
Agent
25. Polyglot for Maven
Maven can support different formats and even DSLs
‣
A lot of work has been done recently on the Ruby and Scala DSLs, but there is support for Groovy, Atom,
YAML, and Clojure as well
‣
‣
We cut the 0.9.0 release yesterday and it’s available to try
The code and instructions are available at https://github.com/tesla/tesla-polyglot
26. project 'Polyglot Tesla :: Aggregator' do
model_version '4.0.0'
id 'io.tesla.polyglot:tesla-polyglot:0.0.1-SNAPSHOT'
inherit 'io.tesla:tesla:4'
packaging 'pom'
properties( 'sisuInjectVersion' => '0.0.0.M2a',
'teslaVersion' => '3.1.0' )
modules [ 'tesla-polyglot-common',
'tesla-polyglot-atom',
'tesla-polyglot-ruby',
'tesla-polyglot-groovy',
'tesla-polyglot-yaml',
'tesla-polyglot-clojure',
'tesla-polyglot-scala',
'tesla-polyglot-cli',
'tesla-polyglot-maven-plugin' ]
overrides do
jar 'org.eclipse.sisu:org.eclipse.sisu.inject:${sisuInjectVersion}'
jar 'org.eclipse.sisu:org.eclipse.sisu.plexus:${sisuInjectVersion}'
jar 'org.apache.maven:maven-model-builder:3.1.0'
jar 'org.apache.maven:maven-embedder:3.1.0'
jar( 'junit:junit:4.11', :scope => 'test' )
end
plugin 'org.codehaus.plexus:plexus-component-metadata:1.5.4' do
execute_goals 'generate-metadata', 'generate-test-metadata'
end
build do
execute("first", :validate) do |context|
puts "Hello from JRuby!"
end
end
end
27. project {
modelVersion '4.0.0'
parent('io.tesla:tesla:4')
groupId 'io.tesla.polyglot'
artifactId 'tesla-polyglot'
version '0.0.1-SNAPSHOT'
packaging 'pom'
name 'Polyglot Tesla :: Aggregator'
modules([
'tesla-polyglot-common',
'tesla-polyglot-atom',
'tesla-polyglot-ruby',
'tesla-polyglot-groovy',
'tesla-polyglot-yaml',
'tesla-polyglot-clojure',
'tesla-polyglot-scala',
'tesla-polyglot-cli',
'tesla-polyglot-maven-plugin',
])
properties {
sisuInjectVersion '0.0.0.M2a'
teslaVersion '3.1.0'
}
dependencyManagement {
dependencies {
dependency('org.eclipse.sisu:org.eclipse.sisu.inject:${sisuInjectVersion}')
dependency('org.eclipse.sisu:org.eclipse.sisu.plexus:${sisuInjectVersion}')
dependency('org.apache.maven:maven-model-builder:3.1.0')
dependency('org.apache.maven:maven-embedder:3.1.0')
dependency('junit:junit:4.11:test')
}
}
build {
$execute(id: 'hello', phase: 'validate') {
println ""
println "hello, I am Groovy inside Maven. What? What am I doing here?? I thought he was my arch nemesis! I'm confused."
println ""
}
}
}
plugins {
plugin('org.codehaus.plexus:plexus-component-metadata:1.5.4') {
executions {
execution(goals: ['generate-metadata', 'generate-test-metadata'])
}
}
}
32. Mavenize like a champ.
Introduction to Maven Virtual Training
Thursday, February 13, 2014
1:00PM-7:30PM EST (UTC -5 hours)
575CAD/student
Small classes, an accomplished instructor, top-notch training…all from
the comfort of your own pajamas office. Learn more at www.takari.io