Bug in Gradle 2.14-rc1 - No service of type StyledTextOutputFactory

I tried updating to Gradle 2.14-rc-1 and am now getting an error stating “No service of type StyledTextOutputFactory” when using Spring’s dependency management plugin. You can find a sample project illustrating the problem in github at rwinch/gradle-2.14-rc1-bug/tree/gradlew-2.14-rc-1.

You can find the complete stacktrace below:

$ ./gradlew tasks --stacktrace

FAILURE: Build failed with an exception.

* Where:
Build file '/Users/rwinch/Downloads/gradle-2.14-rc1-bug/build.gradle' line: 15

* What went wrong:
A problem occurred evaluating root project 'gradle-2.14-rc1-bug'.
> Failed to apply plugin [class 'io.spring.gradle.dependencymanagement.DependencyManagementPlugin']
   > Could not create task of type 'DependencyManagementReportTask'.

* Try:
Run with --info or --debug option to get more log output.

* Exception is:
org.gradle.api.GradleScriptException: A problem occurred evaluating root project 'gradle-2.14-rc1-bug'.
        at org.gradle.groovy.scripts.internal.DefaultScriptRunnerFactory$ScriptRunnerImpl.run(DefaultScriptRunnerFactory.java:93)
        at org.gradle.configuration.DefaultScriptPluginFactory$ScriptPluginImpl$2.run(DefaultScriptPluginFactory.java:177)
        at org.gradle.configuration.ProjectScriptTarget.addConfiguration(ProjectScriptTarget.java:77)
        at org.gradle.configuration.DefaultScriptPluginFactory$ScriptPluginImpl.apply(DefaultScriptPluginFactory.java:182)
        at org.gradle.configuration.project.BuildScriptProcessor.execute(BuildScriptProcessor.java:38)
        at org.gradle.configuration.project.BuildScriptProcessor.execute(BuildScriptProcessor.java:25)
        at org.gradle.configuration.project.ConfigureActionsProjectEvaluator.evaluate(ConfigureActionsProjectEvaluator.java:34)
        at org.gradle.configuration.project.LifecycleProjectEvaluator.evaluate(LifecycleProjectEvaluator.java:55)
        at org.gradle.api.internal.project.AbstractProject.evaluate(AbstractProject.java:540)
        at org.gradle.api.internal.project.AbstractProject.evaluate(AbstractProject.java:93)
        at org.gradle.execution.TaskPathProjectEvaluator.configureHierarchy(TaskPathProjectEvaluator.java:42)
        at org.gradle.configuration.DefaultBuildConfigurer.configure(DefaultBuildConfigurer.java:35)
        at org.gradle.initialization.DefaultGradleLauncher$2.run(DefaultGradleLauncher.java:124)
        at org.gradle.internal.Factories$1.create(Factories.java:22)
        at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:91)
        at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:53)
        at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:121)
        at org.gradle.initialization.DefaultGradleLauncher.access$200(DefaultGradleLauncher.java:32)
        at org.gradle.initialization.DefaultGradleLauncher$1.create(DefaultGradleLauncher.java:98)
        at org.gradle.initialization.DefaultGradleLauncher$1.create(DefaultGradleLauncher.java:92)
        at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:91)
        at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:63)
        at org.gradle.initialization.DefaultGradleLauncher.doBuild(DefaultGradleLauncher.java:92)
        at org.gradle.initialization.DefaultGradleLauncher.run(DefaultGradleLauncher.java:83)
        at org.gradle.launcher.exec.InProcessBuildActionExecuter$DefaultBuildController.run(InProcessBuildActionExecuter.java:99)
        at org.gradle.tooling.internal.provider.ExecuteBuildActionRunner.run(ExecuteBuildActionRunner.java:28)
        at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
        at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:48)
        at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:30)
        at org.gradle.launcher.exec.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:81)
        at org.gradle.launcher.exec.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:46)
        at org.gradle.launcher.daemon.server.exec.ExecuteBuild.doBuild(ExecuteBuild.java:52)
        at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
        at org.gradle.launcher.daemon.server.exec.WatchForDisconnection.execute(WatchForDisconnection.java:37)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
        at org.gradle.launcher.daemon.server.exec.ResetDeprecationLogger.execute(ResetDeprecationLogger.java:26)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
        at org.gradle.launcher.daemon.server.exec.RequestStopIfSingleUsedDaemon.execute(RequestStopIfSingleUsedDaemon.java:34)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
        at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:74)
        at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:72)
        at org.gradle.util.Swapper.swap(Swapper.java:38)
        at org.gradle.launcher.daemon.server.exec.ForwardClientInput.execute(ForwardClientInput.java:72)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
        at org.gradle.launcher.daemon.server.health.DaemonHealthTracker.execute(DaemonHealthTracker.java:47)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
        at org.gradle.launcher.daemon.server.exec.LogToClient.doBuild(LogToClient.java:60)
        at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
        at org.gradle.launcher.daemon.server.exec.EstablishBuildEnvironment.doBuild(EstablishBuildEnvironment.java:72)
        at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
        at org.gradle.launcher.daemon.server.health.HintGCAfterBuild.execute(HintGCAfterBuild.java:41)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
        at org.gradle.launcher.daemon.server.exec.StartBuildOrRespondWithBusy$1.run(StartBuildOrRespondWithBusy.java:50)
        at org.gradle.launcher.daemon.server.DaemonStateCoordinator$1.run(DaemonStateCoordinator.java:237)
        at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:54)
        at org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableExecutorImpl.java:40)
Caused by: org.gradle.api.internal.plugins.PluginApplicationException: Failed to apply plugin [class 'io.spring.gradle.dependencymanagement.DependencyManagementPlugin']
        at org.gradle.api.internal.plugins.DefaultPluginManager.doApply(DefaultPluginManager.java:153)
        at org.gradle.api.internal.plugins.DefaultPluginManager.addImperativePlugin(DefaultPluginManager.java:67)
        at org.gradle.api.internal.plugins.DefaultPluginManager.addImperativePlugin(DefaultPluginManager.java:73)
        at org.gradle.api.internal.plugins.DefaultPluginContainer.apply(DefaultPluginContainer.java:60)
        at org.springframework.boot.gradle.dependencymanagement.DependencyManagementPluginFeatures.apply(DependencyManagementPluginFeatures.java:44)
        at org.springframework.boot.gradle.SpringBootPlugin.apply(SpringBootPlugin.java:47)
        at org.springframework.boot.gradle.SpringBootPlugin.apply(SpringBootPlugin.java:38)
        at org.gradle.api.internal.plugins.ImperativeOnlyPluginApplicator.applyImperative(ImperativeOnlyPluginApplicator.java:35)
        at org.gradle.api.internal.plugins.RuleBasedPluginApplicator.applyImperative(RuleBasedPluginApplicator.java:43)
        at org.gradle.api.internal.plugins.DefaultPluginManager.doApply(DefaultPluginManager.java:137)
        at org.gradle.api.internal.plugins.DefaultPluginManager.apply(DefaultPluginManager.java:112)
        at org.gradle.api.internal.plugins.DefaultObjectConfigurationAction.applyType(DefaultObjectConfigurationAction.java:113)
        at org.gradle.api.internal.plugins.DefaultObjectConfigurationAction.access$200(DefaultObjectConfigurationAction.java:36)
        at org.gradle.api.internal.plugins.DefaultObjectConfigurationAction$3.run(DefaultObjectConfigurationAction.java:80)
        at org.gradle.api.internal.plugins.DefaultObjectConfigurationAction.execute(DefaultObjectConfigurationAction.java:136)
        at org.gradle.api.internal.project.AbstractPluginAware.apply(AbstractPluginAware.java:46)
        at org.gradle.api.internal.project.ProjectScript.apply(ProjectScript.java:34)
        at org.gradle.api.Script$apply$0.callCurrent(Unknown Source)
        at build_67iyc93lbs2oggqb0jp53e8pk.run(/Users/rwinch/Downloads/gradle-2.14-rc1-bug/build.gradle:15)
        at org.gradle.groovy.scripts.internal.DefaultScriptRunnerFactory$ScriptRunnerImpl.run(DefaultScriptRunnerFactory.java:91)
        ... 58 more
Caused by: org.gradle.api.tasks.TaskInstantiationException: Could not create task of type 'DependencyManagementReportTask'.
        at org.gradle.api.internal.project.taskfactory.TaskFactory$1.call(TaskFactory.java:123)
        at org.gradle.api.internal.project.taskfactory.TaskFactory$1.call(TaskFactory.java:118)
        at org.gradle.util.GUtil.uncheckedCall(GUtil.java:401)
        at org.gradle.api.internal.AbstractTask.injectIntoNewInstance(AbstractTask.java:176)
        at org.gradle.api.internal.project.taskfactory.TaskFactory.create(TaskFactory.java:118)
        at org.gradle.api.internal.project.taskfactory.TaskFactory.createTask(TaskFactory.java:77)
        at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory.createTask(AnnotationProcessingTaskFactory.java:101)
        at org.gradle.api.internal.project.taskfactory.DependencyAutoWireTaskFactory.createTask(DependencyAutoWireTaskFactory.java:39)
        at org.gradle.api.internal.tasks.DefaultTaskContainer.create(DefaultTaskContainer.java:62)
        at org.gradle.api.internal.tasks.DefaultTaskContainer.create(DefaultTaskContainer.java:97)
        at org.gradle.api.internal.tasks.DefaultTaskContainer.create(DefaultTaskContainer.java:127)
        at org.gradle.api.internal.tasks.DefaultTaskContainer_Decorated.create(Unknown Source)
        at org.gradle.api.internal.tasks.DefaultTaskContainer_Decorated$create.call(Unknown Source)
        at io.spring.gradle.dependencymanagement.DependencyManagementPlugin.apply(DependencyManagementPlugin.groovy:64)
        at io.spring.gradle.dependencymanagement.DependencyManagementPlugin.apply(DependencyManagementPlugin.groovy)
        at org.gradle.api.internal.plugins.ImperativeOnlyPluginApplicator.applyImperative(ImperativeOnlyPluginApplicator.java:35)
        at org.gradle.api.internal.plugins.RuleBasedPluginApplicator.applyImperative(RuleBasedPluginApplicator.java:43)
        at org.gradle.api.internal.plugins.DefaultPluginManager.doApply(DefaultPluginManager.java:137)
        ... 77 more
Caused by: org.gradle.internal.service.UnknownServiceException: No service of type StyledTextOutputFactory available in ProjectScopeServices.
        at org.gradle.internal.service.DefaultServiceRegistry.getServiceProvider(DefaultServiceRegistry.java:436)
        at org.gradle.internal.service.DefaultServiceRegistry.doGet(DefaultServiceRegistry.java:426)
        at org.gradle.internal.service.DefaultServiceRegistry.get(DefaultServiceRegistry.java:414)
        at org.gradle.api.internal.DependencyInjectingInstantiator.convertParameters(DependencyInjectingInstantiator.java:81)
        at org.gradle.api.internal.DependencyInjectingInstantiator.newInstance(DependencyInjectingInstantiator.java:54)
        at org.gradle.api.internal.ClassGeneratorBackedInstantiator.newInstance(ClassGeneratorBackedInstantiator.java:36)
        at org.gradle.api.internal.project.taskfactory.TaskFactory$1.call(TaskFactory.java:121)
        ... 94 more

Hi @Rob,

The problem here is that StyledTextOutputFactory is an Internal Gradle service. Strictly speaking, plugins should not rely on internal gradle classes or services, which are subject to change without notice.

The root of the issue is here. It may be worth opening an issue with dependency-management-plugin. While not at all encouraged with Gradle 2.14+ it may be possible to inject the class org.gradle.internal.logging.text.StyledTextOutputFactory

Thanks for the reply @Adrian_Kelly.

The import is org.gradle.logging.StyledTextOutputFactory The package name does not have internal in it. Can I ask why org.gradle.logging.StyledTextOutputFactory is considered an internal API?

Things are in flux at the moment and we are gradually moving more and more internal types over to the their appropriate internal packages. This can be a delicate process and can introduce breaking changes as you have just encountered :wink: There is an ongoing concerted effort to move all internal types under internal packages for the next major Gradle release.

org.gradle.logging.StyledTextOutputFactory is considered an internal API because we want the ability to change the the styling of core Gradle generated console output, without breaking external plugins. Gradle’s console styling was, intentionally, not designed as an all-encompassing console output formatter for use in external build scripts and plugins. Gradle’s logging abstraction is the recommended way for plugins and build scripts to output to the console.

As it turns out the particular issue you found will be fixed in RC2 see: https://github.com/gradle/gradle/commit/0182abff98fad5249c9f0c0033231ef858e21f28

The rule is, if it’s not in the javadoc it’s internal. Admittedly, the combination of the “rule” not really being explicitly stated anywhere, in combination with inconsistent usage of “internal” in package names, makes this all a bit confusing. As stated above, we are slowly trying to move towards solving the latter, but this often means breaking folks’s stuff.

Thanks for the replies, explanation, and the fix.

I was not aware of the rule that it must be in the javadoc. That will make it a little easier to ensure plugins work seamlessly with updated Gradle versions.

I created a ticket for Spring’s Dependency Management Plugin to remove the now deprecated API.

Thanks again!
Rob

If third-party plugins aren’t supposed to use StyledTextOutputFactory or StyledTextOutput, what’s the recommended approach for producing output that’s consistent with the colour scheme used by first-party plugins? As far as I can tell, the logging support isn’t a fully featured replacement. The task in question is specifically intended to report some information to the user, in a similar manner to the built-in dependencies task.

That’s correct @Andy_Wilkinson, logging is just “logging”. For things that need good visualisation and styling it’s probably best to generate html reports. We ourselves, are moving away from enhancing or creating first party (gradle core) plugins which leverage console styling in favour of other visual formats and mediums.

FWIW, I think that’s a shame and is a step backwards for Gradle.

As I mentioned above, the task is somewhat analogous to the core dependencies task. Producing an HTML file, for example, will make the user experience worse as it adds some extra steps to accessing the information.

If the dependencies task in 3.0 will continue to produce styled console output then I really think Gradle should provide an API that allows third-party plugins to do the same. Without such an API, third-party plugins are either left reinventing the wheel or looking like they don’t really fit.

1 Like

I’m developing a plugin to support building of Xcode projects using gradle (https://github.com/openbakery/gradle-xcodePlugin) and I use the StyledTextOutput and also the ProgressLogger to have a nice output on the console. In the background I use the xcodebuild command line tool for compiling and I grab the output and make it nice. e.g. the current compiled file is shown using the ProgressLogger but not logged. The reason I do this is to only log the important stuff. If a file successfully compiles, than I do not log this. If a warning or an compile error occurs, than this is logged on the console.
Here I also use different colors with the StyledTextOutput. I use red for a compile error, and yellow for a warning.

In my opinion it does not make sense for plugins to use only the “logging” or html report for vizualization. And I’m with @Andy_Wilkinson that this is a step backwards.

I will use the internal APIs in my plugin, because I want I nice output. The downside now is that I have to modify my plugin to work with gradle 2.14+, because you have moved the stuff to an internal package.
I also use backward compatibly to older gradle versions.

2 Likes