Numerous updates to the Spring CLI, primarily for better embedded REPL
shell support:
* Refactor the CLI application to help separate concerts between the
main CLI and the embedded shell. Both the CLI and embedded shell now
delegate to a new `CommandRunner` to handle running commands. The
runner can be configured differently depending depending on need.
For example, the embedded shell adds the 'prompt' and 'clear'
commands.
* Most `Command` implementations have been moved to sub-packages so that
they can be co-located with the classes that they use.
* Option commands are now only used in the CLI, the embedded shell
does not user them and details have been removed from the Command
interface.
* The REPL shell has been significantly refactored to:
- Support CTRL-C to cancel the running process. This is supported
when running external commands and most internal commands.
- Fork a new JVM when running commands (primarily for CTRL-C support
but also for potential memory and classpath issues)
- Change the "continue" trigger from `<<` to `\`
- Support command completion of files
- Add ANSI color output
- Provide 'help' support for internal commands (such as 'clear')
- Remove the now redundant `stop` command
Fixes gh-227
The AST transformation that processes @Grab annotations is driven once
per source file. Previously, this meant that if an app consisted of
multiple source files then multiple, discrete dependency resolutions
would be performed.
This commit updates AetherGrapeEngine to cache a previous resolution's
outcome and use its dependency to influence the outcome of subsequent
resolutions. For example if a one resolution results in spring-core
4.0.0.RELEASE being added to the classpath, subsequent resolutions
that depend upon spring-core will always get the 4.0.0.RELEASE
version. This is achieved by using the dependencies found by earlier
resolutions as dependency management configuration of the current
resolution. This removes the possibility of multiple versions of the
same dependency ending up on the classpath.
In addition to using the results of earlier resolutions to provide
dependency management configuration, default dependency management
configuration is also provided. This configuration is specified by
the springcli.properties file and ensures that, where Boot prescribes
certain versions of a dependency, that is the version that will be
resolved. For example, this ensures that spring-data-redis, which
depends upon Spring 3.1.4, pulls in the version of Spring that Boot
requires instead.
Fixes#224
Actually System.in works fine, it's the output streams that get buffered.
We can fix it by diverting them for the duration of the command.
Fixes gh-217
We might also want to rethink "!" as a shell exec command (since it means
something in a real shell and in JLine). E.g. use "exec" or something.
Partial fix for gh-220 (ideally we'd process the events and catch
and handle exceptions).
In this commit we retain "init" as a command inside the ShellCommand
but not on the bash command line.
Seems to have an impact on performance so relevant to gh-212.
Update SpringApplication to run by default in 'headless' mode. This
prevents the AWT system from creating a Java icon (for example in the
OSX dock).
Also update builds to run tests in 'headless' mode.
This appears to be a significant improvement in performance
(checking for the existence of init.grooy is cheap, but compiling
it is expensive).
I'm going to say this fixes gh-212.
Replace references to 'files' throughout the code-base with 'sources'
following the rename of `FileOptions` to `SourceOptions`.
Also cleanup ResourceUtils a little
We check for existence of the sources and (as before) resolve multiple
resources on the classpath if a path is not a File. In addition supports
Spring pseudo-URL prefixes as well as normal URLs as source locations.
In addition sources can now be specified as a directory (searched
recursively by default), or a resource pattern (e.g. app/**/*.groovy).
Fixes gh-207
Recent changes to the repository configuration for @Grab
didn't update the tests which use the GroovyCompiler as
a standalone. Fixed that by using the
RepositoryConfigurationFactory.
Previously, there were two <manifestEntries> elements in the CLI's
pom.xml. With certain versions of Maven, this appeared to cause the
first element to be ignored in favour of the second. The problem did
not occur when built locally with Maven 3.1.1, but did occur when built
by Bamboo which, I believe, uses 3.0.x
This commit combines the two <manifestEntries> into one.
The test passes locally, both in Eclipse and on the command line, but
fails on the CI server. Revert the addition of the test while I
hopefully figure out why.
This reverts commit 2e81b1d0d0.
The grab command downloads the dependencies of one or more Groovy
scripts to ./repository. This commit ensures that those previously
downloaded dependencies can be used by a subsequent invocation of the
run command.
The location and behaviour of the local cache is unaffected by this
change. If the dependencies in ./repository do not exist in the local
cache, Aether will "download" them from ./repository and store them in
the local cache.
Fixes#191
Previously, Aether's configuration was largely hard-coded making it
impossible to configure a mirror, provide credentials for accessing
a repository, etc.
This commit adds support for configuring Aether via Maven's
settings.xml file. The support is optional and must be enabled by
grabbing spring-boot-maven-settings in an init script. The Aether
instance that's used when running the application will then be
configured using settings.xml. The settings file is expected to be
found in ${user.home}/.m2/settings.xml.
The configuration of the following items is currently supported:
- Offline
- Proxies
- Mirrors
- Server authentication
- Local repository location
If the support is not enabled, settings.xml does not exist, or
settings.xml does not configure certain things then sensible defaults
are applied.
When an init command is run, it may add entries to the classpath. This
commit adds a test that verifies that, if an entry that is added to
the classpath contains a CompilerAutoConfiguration file in
META-INF/services, then the CompilerAutoConfigurations declared in it
are found by subsequent ServiceLoader.load calls.
Previously, a transform was used to add @GrabResolver annotations
during compilation that added the Spring milestone and snapshot
repositories. This functionality is now handled by
RepositoryConfigurationFactory so the transform is no longer required.
Users can declare or Command, OptionHandler classes in an init script
or they can use a DSL, e.g.
command("foo") { args -> println "Do stuff with ${args} array" }
or
command("foo") {
options { option "bar", "Help text for bar option" ithOptionArg() ofType Integer }
run { options -> println "Do stuff with ${options.valueOf('bar')}" }
}
InitCommand runs on creation of SpringCli so it can search for additional
Commands in updated classpath. Also added as interactive command in Shell
session.
PropertiesLauncher now supports creating its own class loader
from looader.classLoader property. It will succeed if the
implementation specified has a default constructor or one
that takes a parent class loader, or one that takes a URL[]
and a parent class loader (like URLClassLoader).
Change SpringCli so that running without arguments no longer jumps into
the embedded REPL shell. This restores the ability to obtain quick usage
help by simply typing `spring` from the command prompt.
Windows users or developers that prefer the embedded shell can still
launch it using `spring shell`.
Change OptionHandler to support '-cp' instead of '--cp'. This update
to the original fix (045088e8b) renders `help` output correctly and
should prevent potential issues if a `-p` command is added in the future.
Fixes gh-178
Main user-facing interface is still Counter/GaugeService but the
back end behind that has more options. The Default*Services write
metrics to a MetricWriter and there are some variants of that, and
also variants of MetricReader (basic read-only actions).
MetricRepository is now a combination of MetricReader, MetricWriter
and some more methods that make it a bit more repository like.
There is also a MultiMetricReader and a MultiMetricRepository for
the common case where metrics are stored in related (often open
ended) groups. Examples would be complex metrics like histograms
and "rich" metrics with averages and statistics attached (which
are both closed) and "field counters" which count the occurrences
of values of a particular named field or slot in an incoming message
(e.g. counting Twitter hastags, open ended).
In memory and redis implementations are provided for the repositories.
Generally speaking the in memory repository should be used as a
local buffer and then scheduled "exports" can be executed to copy
metric values accross to a remote repository for aggregation.
There is an Exporter interface to support this and a few implementations
dealing with different strategies for storing the results (singly or
grouped).
Codahale metrics are also supported through the MetricWriter interface.
Currently implemented through a naming convention (since Codahale has
a fixed object model this makes sense): metrics beginning with "histogram"
are Histograms, "timer" for Timers, "meter" for Meters etc.
Support for message driven metric consumption and production are provided
through a MetricWriterMessageHandler and a MessageChannelMetricWriter.
No support yet for pagination in the repositories, or for HATEOAS style
HTTP endpoints.