BLOG
28 August 2018

Case Study – Library Releases and How to Do Them

tech

One day I said: enough. This was the day when I tried to copy my MVP code, yet again, to another project. On that day I thought, “how about applying the best practices to this MVP code, like reusability?”. And then my library journey began. It involved, and still does, building artifacts, releasing and uploading repositories, and all that jazz.

The Internet of
      Things
The Internet of Things

If you’re thinking about releasing a library to the public, this article is for you. Here, I will describe my attempts to prepare and share code with the public successfully. As a kind of foreword: It will be about the Android library, with the Gradle build system. The target release audience will be both private via VSTS (Visual Studio Team Services) and public via jcenter and Bintray.

Kotlin MVP

This Android library, the leading star of this article, is the result of my effort to improve the quality of my code and my work by eliminating repetition. This is a Kotlin-powered MVP pattern, responsible for structuring the activities and fragments in your app (the basic components, for those non-android folks out there). To read about the MVP itself, I suggestthis article. But enough about the library, let’s get to the real content of this article.

Picking the release target. Vol. 1: Private

Well, this private release thing came about by accident. I was asking around for some method to publish my library. So someone suggested VSTS as a way to release it. So I went there, had no idea what to do, then stumbled onto this neat aid. It explained some things, like that I needed to create a feed (also called a repository). The feed is a collection of packages. The package, on the other hand, is a collection of versions. While version is a collection of… erm, seems fairly simple, right? Let’s complement this with an example from KotlinMVP.
Feed is kinda less visible on the client’s side. It is called SHMaven. So my KotlinMVP is located in SHMaven.
The package is KotlinMVP. So SHMaven has several packages, one of them being KotlinMVP.
And finally, the KotlinMVP package has several versions, like 1.0.0.
SHMaven -> KotlinMVP -> 1.0.0
While digging more into the VSTS and that guide, I noticed the private key.


So I realised that this is only for people who provide such a key, along with the proper URL. Not so convenient, but in the end, I kept this configuration on a separate branch just as a way to get a private version, not released to the public.

Proceeding to config

The very first thing I did was creating the above feed. Package and version will be provided by the actual publish.

Create New Feed
Create New Feed

So far so good. In this neat aid, I’ve copied the gradle code and pasted it into my project, just as suggested. Later, I rearranged what needed rearranging and filled out the blanks with my data, so for example, the publication information was like this:


So it becomes clear right now. The `groupId` is, most preferably, your company address (java-package-esque), while the `artifactId` is your library name, and `version` is, erm, version name ? . Here we also point to the location of the release’s aar (which is just a fancy java jar, with some additional stuff from Android added).
All the above makes up the most important thing from the client-side point of view: this line of code

And the target publishing information was

Then, all I needed was, seemingly, to invoke this little Gradle task called publish just like this: gradle publish
But it did not work. It is a good command. So why didn’t it work for me? Well, let’s get somewhat in-depth on the issue. A typical computer of an Android developer has two gradles in it: The global one and the project one, also known as the wrapper. The global one has to be configured to work as a global command in the Windows environment, and mine wasn’t. I ended up using `gradlew` , that is, the gradle wrapper.
gradlew publish
Moreover, after I invoked that (it kinda, sort of, worked), I got yet another error. This time, it was a 404 from the service. I was baffled, checked everything twice or more.

After an extended period of searching and checking code I noticed, that the feed has the Connect to feed option.

SHMaven
SHMaven

As a result, I received some code to paste here and there:


And after that, I just ran this simple command:gradlew publish
And voila! Library published. Or is it? Problem solved, right? Apparently not. I had to combine the connect to feed code with the above code from that help source. Of course, in the meantime, Icommented out the help source code and put only the above. That didn’t work either.
As the 404 was coming from a URL, I figured out that only the URL was wrong, so I got the one from connect to feed. And it worked. Really!
After invoking gradlew publish in the SHMaven repository (the feed), the KotlinMVP package appeared with its version of 1.0.0.
I imported it by adding this to the other project’s Gradle:
implementation 'com.softwarehut:KotlinMVP:1.0.0'
And it worked, my project read the dependency, and it was smooth and good and great. Well, I got a big fat NO. This was the beginning of even more trouble.

Publishing. Vol. 1: Private edition – dependency problems

As you can see, my project had this pretty little dependency


And dependencies in gradle/maven publishing do not go to the release’s aar package (the mvp-release.aar jar). It would be a bad idea, really, to include all the binaries in your binary. But most importantly, the generated pom file (gradle generates maven’s pom file with release information in the process) did not have the information to download all the necessary dependencies, like rxjava:2.1.14-RC1.
Turns out you have to provide that manually. Edit the artifact publishing info like this:

With this, the package (via pom file) will have the information to download the necessary dependencies.
That got the job done. The package was released as requested, and Gradle downloaded all dependencies.

The final config


And you need to declare in your gradle.properties file:

The client-side config


Moreover, you need to specify that token in the gradle.properties file.

Conclusion of vol. 1: Private publish

There are a few problems with the above, namely:
There is some kind of token requested, the privacy needs it.
It’s quite a lot of lines for a single dependency.
It is private, I can’t show it to the public in this state.
Now, it’s time for vol. 2.

Vol. 2: Public publish – jcenter and Bintray

This time, I had no help from the outside because no one I know has done this before.To register on jcenter, one needs to get an account on Bintray. The journey there is similar to the one on VSTS.
You need to create a repository (instead of feed), then a package, and finally a version. There are two options to do this: manually, via a website and via a plugin.
I tried to do it via a website. It was nice, up until uploading the files. There, I needed to modify my publishing code because Bintray requires a generated pom file.


So the pom file will be generated in a repo folder. Having both aar and pom files, I proceeded to upload these to the website. The upload was successful, along with the publish. Well, only the publish operation was successful, the effect was not. My other project did not find the dependency.
Also, the dependency code changed:

The public release continues

After a long search, with many errors, I gave up on releasing the version manually and set up the official plugin. In the end, all I needed to do was to change the command to:
gradlew bintrayUpload
instead of publish, and fill this with my info:


My publication, in this case, was the publishing code above in the publications container. And that was it. Files were uploaded properly, I clicked the magical publish button, and the other project could then access the dependency through Maven. Time for the final step!

Releasing to jcenter

The jcenter needs one more thing: the source code jar artifact, so it complies to open-sourceness. To do this, I had to add this gradle task:


and change the myPublication so it includes artifact sourcesJar, and that was it. Now the jar was generated and put as an additional artifact into the release’s aar.
After all the above, all I needed was to link my newest release to the jcenter on the Bintray website. This can be done by clicking Maven Central. The request will be sent immediately. In about 30 or so minutes, it should be approved. Now users can access the library via

The conclusion

After a very long trial and error process, I was successful in my publishing efforts. Now I internally have two branches – one with private publish and private dependencies, and one with everything public. Just as I wanted.



Author
Maciej Puchalski
Software Developer

Mobile programming enthusiast with Android focus and some multiplatform experience as well. What is more, he also has some years in web development in .NET. Despite these nuisances in his mobile career, he always gets back to Android development. The best part of programming for him is not the implementation itself, but the structuring of code and usage both design patterns and clean code principles. He likes Google ecosystem and is a very active user of their notes app, Google Keep, along with their devices. Progress has been made there to the point of reaching the limit of categories. It gives a point about how he likes his notes to be structured and plentiful. Personally an active Dungeons & Dragons tabletop player with major experience. Also, a cyclist that loves his bicycle.