Create mavenPublication in java

We are working on migrating our current custom plugins from groovy to java and are facing issues getting publications to work. What we want to achieve is to have some jars/zips published onto one out of two maven repos (depending or “type of release” we would post to different repos).

Here is the java code that create the publication that causes the failure:

public class SetupPublicationTask extends DefaultTask {
  @TaskAction
  public void execute() {
    Project project = getProject();
    project.getLogger().info("Creating Maven publication with name mavenJava");
    MavenPublication publication = project.getExtensions().getByType(PublishingExtension.class).getPublications()
            .create("mavenJava", MavenPublication.class);
    publication.from(project.getComponents().getByName("java"));
    publication.setGroupId(project.getGroup().toString());
    publication.setArtifactId(project.getName());

    PublishArtifactSet artifactSet = project.getConfigurations().getByName("archives").getArtifacts();

    ArrayList<PublishArtifact> artifacts = new ArrayList<>(artifactSet);
    project.getLogger().info("Adding archives: {} to Maven publication...", artifacts.stream()
            .map(a -> a.getName()+ "-"+a.getExtension()).collect(Collectors.joining(",")));
    publication.setArtifacts(artifacts);
   }
}

This fails with error:
A problem was found with the configuration of task ‘:release’.
> No value has been specified for property ‘publication.publishableFiles’.

The working groovy code looks like

Task createUploadLibraryTask(Project addToProject, boolean isProductionRelease, String repoUrl, String repoUser, String repoUserPass) {
    String usedRepo = isProductionRelease ? LIBS_REPO : BETA_LIBS_REPO
    project.logger.info("Using library repo: {}",usedRepo)
    addToProject.plugins.apply('maven-publish')
    addToProject.publishing {
        publications {
            mavenJava(MavenPublication) {
                from addToProject.components.java
                artifact addToProject.sourceJar {
                    classifier "sources"
                }
                artifact addToProject.javadocJar {
                    classifier "javadoc"
                }
            }
        }
        repositories {
            maven {
                url repoUrl+"/"+usedRepo
                credentials {
                    username repoUser
                    password repoUserPass
                }
            }
        }
    }
    Task publishTask = addToProject.getTasks().getByPath("publish")
    return publishTask;
}

Publications are naturally based on software components or archiving tasks, so this one works for us:

That’s the default for java plugins, other plugins provide other software componentens, unfortunately the plugins do not provide any String constants for their component names. For publishing there is one main component, the metadata (pom.xml) will be based on all informations relevant for this component:

        final PublishingExtension publishingExt = project.getExtensions().getByType(PublishingExtension.class);
        final MavenPublication mavenPublication = publishingExt.getPublications().maybeCreate(ProjectUtils.PUBLICATION_NAME, MavenPublication.class);
        mavenPublication.from(project.getComponents().getByName("java"));

everything else is just a addition the the main component and should be added as artifact. But I think the best way is to just reference the producing tasks:

        final Jar sourcesJarTask = project.getTasks().create("sourcesJar", Jar.class);
        final SourceSet mainSourceSet = project.getConvention().getPlugin(JavaPluginConvention.class).getSourceSets().getByName(SourceSet.MAIN_SOURCE_SET_NAME);
        sourcesJarTask.from(mainSourceSet.getAllSource());
        sourcesJarTask.getArchiveClassifier().set("sources");
        sourcesJarTask.dependsOn(JavaPlugin.CLASSES_TASK_NAME);

        final PublishingExtension publishingExt = project.getExtensions().getByType(PublishingExtension.class);
        final MavenPublication mavenPublication = publishingExt.getPublications().maybeCreate(ProjectUtils.PUBLICATION_NAME, MavenPublication.class);
        mavenPublication.artifact(sourcesJarTask);

This way the classifier is provided by the Jar task and one does not have to set it again for publishing.

Hope this helps.

btw. if one wants to use cross project dependencies to lets say test-classes one still needs to provide a separate configuration with archives, as I found no way to adress a classified publication in project dependencies (within the same multimodule project)