DSP2017

DSP 2017 – Summary

2017-05-31 DSP2017 2 comments

Introduction

Some time ago, I’ve decided to participate in “Get Noticed 2017” (“Daj się poznać” in Polish) competition. It’s competition for Polish programmers in which people have to create a blog if they don’t have it (luckily, I could skip that step) and write at least 2 articles per week from the beginning of the March til the end of May, which is exactly today (for 3 months). Posts had to be categorized on the blog. You can find all my posts related to this competition in DSP2017 category. Besides this, competitors had to create their own open-source projects (or one project) and contribute to them during the competition. I already had my projects, so I kept resolving planned issues within them. Nevertheless, I created new, small projects. I treated that competition as a challenge and possibility to try something new. Moreover, it was some kind of motivation for doing more stuff. I already had a blog and OS projects, so I thought it will be easy for me and I’ll just keep doing what I already do. I was a little bit wrong.

Blogging

I’ve written 28 articles on this blog in DSP2017 category (including this one). Writing two articles per week is a lot. Previously I was writing approximately 1 article per month or sometimes more when I wanted to. Now I was writing 8 articles per month, so It’s 800% more often than usual. It forced me to be a little bit more organized & creative. I also created a backlog of article topics and a backlog of the software projects (big & small) I wanted to create & eventually, describe.

In the chart below, you can see how the number of the articles increased when I started participating in the competition.

Moreover, I received more comments than usual. The peak in 2015 you see on the picture is an article about Test coverage report for Android application. For some reason, people found it interesting and had a lot of questions.

I observed slightly more visitors on the blog, but not very huge. There was a peak in the beginning of the March, but later it decreased to a bit higher level than it was to the starting point. Below you can see statistics from the Google Analytics from the last 90 days. The drops on the plots are on the weekends. It shows people usually visit my website during the work week. Interesting information is the fact that drop of the visitors in the beginning of the April on the weekend was smaller than usual because I was speaking at the conference, so probably people googled me these days.

Projects

During the DSP2017, I created the following new projects:

  • spotify-cli-linux – a command-line interface to Spotify on Linux written in Python
  • tmux-auto-pane – a tiny tool for creating pre-defined tile layouts in tmux on linux with xdotool written in Bash
  • YaaS Java SDK – Hybris as a Service Java SDK for microservice proxy

During the DSP2017, I updated the following projects:

  • ReactiveBeacons – Android library scanning BLE beacons nearby with RxJava (an update included migration to RxJava2)
  • ReactiveNetwork – Android library listening network connection state and Internet connectivity with RxJava Observables (an update included migration to RxJava2)
  • prefser – Wrapper for Android SharedPreferences with object serialization and RxJava Observables
  • swipe – detects swipe events on Android (with RxJava or listener)
  • pkup – semi-automated generating of PKUP report (tiny tool for formal reporting stuff at my work)

I also updated my dotfiles and a few on my public knowledge sources I store on GitHub, but they are not counted as a “regular projects”

Conferences

During this competition I also gave a talk during Kariera IT Conference in Katowice, Poland titled How to make open-source projects, which people want to use. I was invited to this conference as a speaker, what was very flattering. I also received nice, valuable feedback from the conference organizers. Besides that, I also participated in the J On The Beach conference in Malaga, Spain as an attendee. Unfortunately, I haven’t found time to write an article summarizing this event. I can tell you it was really great. Besides the conference itself, location, weather & food were perfect! I also had to write two articles on the blog for the given week in advance, because I haven’t taken my laptop on this trip.

Summary

To wrap up, participating in this competition was quite challenging and harder than I thought it would be. Nevertheless, it helped me to be consistent and more organized. I also boosted my creativity and ability to produce more articles as well as writing and language skills (English is not my native language). It was hard but fun. The challenge is accomplished! There are over 1000 participants, so I treat this event rather as a challenge for myself than competing with others. Moreover, it’s hard to measure and compare such work among different people. Nevertheless, I’m looking for results anyway :-).

New reactive data types in RxJava2

2017-05-31 DSP2017, Java, RxJava No comments

Introduction

I’m still exploring reactive programming world and RxJava library. Recently, I’ve migrated a few of my open-source libraries from RxJava1 to RxJava2 and written yet another project in RxJava2 from the beginning. Nevertheless, I’m still learning this library and its concept. It’s very wide topic. In RxJava1 we simply had one reactive data type called Observable. In RxJava2, we have more data types like Observable, Flowable, Single, Maybe & Completable. In this article, I’ll briefly explain their purpose and tell you when to use which. The general idea behind these types is code semantics. We should tell consumer of our code, what he or she can expect from our API. Introducing more reactive data types can increase readability and stability of our code base.

Observable

Observable is basically the same Reactive type, we had in RxJava1. It doesn’t have backpressure support.

We should use Observable, when:

  • our data source emits less than 1000 items, so there’s practically no chance of occurring OutOfMemoryException
  • we are working with GUI events, which usually don’t occurs very often and don’t have to be backpressured
  • we are working with synchronous code on legacy JVM like Java 1.6 and we want to have streams features like in Java 8

Observable

Flowable

Flowable type has very similar semantics to Observable. We can operate on Flowable streams with map, flatmap, filter, etc. in the same way as on the Observable type. The main difference is backpressure support.

We should use Flowable when we are:

  • dealing with 10k+ elements in a stream
  • dealing with frequent events (e.g. sensors readings)
  • reading/parsing files from disk
  • reading values from database through JDBC
  • using network/streaming I/O
  • reading/writing to many blocking or pull-based data sources

To learn more, read note about Observable vs. Flowable on wiki of RxJava2 on GitHub.

Single

Single reactive type has been redesigned from scratch in RxJava 2. It’s designed to handle just one event in an asynchronous manner. Good application of this type is single HTTP request when we expect just one response or error and nothing else. It can emit on onSuccess (single value) or onError event (error).

Single

Maybe

Maybe represents a deferred computation and emission of a maybe value or exception. Maybe is a wrapper around an operation/event that may have either:

  • A single result
  • Error
  • No result

Just take a look at the scheme.

The interface of the main consumer of this type have the following methods: onSuccess, onError, onComplete. Conceptually, Maybe is a union of Single and Completable providing the means to capture an emission pattern where there could be 0 or 1 item or an error signaled by some reactive source.

Maybe

Completable

Completable type can be used when we have an Observable that we don’t care about the value resulted from the operation (result is void). It handles only onComplete and onError events. Conceptually, Maybe is a union of Single and Completable providing the means to capture an emission pattern where there could be 0 or 1 item or an error signalled by some reactive source.

Read more about Maybe type on RxJava wiki.

Summary

As we can see, RxJava2 gives us new types, which can help explain our intentions more clearly. We can adjust concrete type to the specific situation. In addition, we can use backpressure for the data sources, which emit a lot of elements to make our projects more robust and stable. Last, but not least RxJava2 is compatible with Reactive Streams API, which is going to be part of the Java 9 specification.

References

Introducing YaaS Java SDK

2017-05-28 DSP2017, Hybris, Java, Open source, RxJava, YaaS No comments

Introduction

In my company, there’s a concept of so-called “innovation day”. I have the possibility to “use” 1 innovation day per 2 development sprints. Last year, I used only 1 day due to the tight release schedule and a lot of work. Now, we are right after release, so I had time to take innovation day once again. I’ve decided to create YaaS Java SDK. If you don’t know what the YaaS is, check out my previous article about Basic usage of YaaS proxy for the microservice. In a few words, it’s a proxy for the microservices with authorization & monitoring capabilities, which allows using other services available on the YaaS market. SDK created by me is really simple, was created in a short period of time and does not cover all features of the YaaS. This SDK allows performing authorized requests to the microservices hidden behind YaaS proxy.

Tech stack used for this project is as follows:

For unit testing I used:

Quick start

I wanted to make this SDK as simple as possible so the user can add YaaS integration to the Java application within just a few lines of code.

YaaSProject project = new YaaSProject.Builder()
    .withClientId("YOUR_CLIENT_ID")
    .withClientSecret("YOUR_CLIENT_SECRET")
    .withOrganization("YOUR_ORGANIZATION")
    .withService("YOUR_SERVICE")
    .withVersion("v1")
    .withZone(Zone.EU)
    .build();

Client client = new YaaS(project);

client.get("path/to/your/endpoint")
    .subscribe(response -> System.out.println(response.body().string()));

As you can see, it looks really simple and straightforward. In the code snippet above, we’ve done the following thigs:

  1. Defined YaaS Project with YaaS service
  2. Created YaaS Client
  3. Performed HTTP GET request to the endpoint of the microservice asynchronously
  4. Received and printed body of the HTTP response from the microservice on the current thread as a String

All of that was done with Single type from RxJava2, which wraps Response type from OkHttp. We have a reactive stream of HTTP response here and we can do with it whatever RxJava2 offers us. Like filtering, mapping, throttling, combining it with other stream and so on.

For more information, visit repository of the project at: https://github.com/pwittchen/yaas-java-sdk.

Future plans

I have the following plans related to this project, which may be realized when I’ll have time:

  • Add more unit tests (I didn’t have enough time to cover all cases)
  • Add continuous integration
  • Integrate YaaS with SAP Hybris Backoffice or SAP Hybris Core Platform through this SDK (PoC)
  • YaaS Android SDK (copy YaaS Java SDK, downgrade it to Java 7 & optionally migrate to Kotlin and create sample mobile app)
  • Optionally, add more features to YaaS Java SDK
  • Optionally, deploy an artifact to Maven Central repository
  • Optionally, create SDKs for different programming languages (especially those I don’t know well or I don’t know at all – just to learn them)

Links

Interesting links related to this article:

Releasing Prefser v. 2.0.7

2017-05-28 Android, DSP2017, Java, Open source No comments

I’ve recently released new version of Prefser. It’s a wrapper for Android SharedPreferences with object serialization and RxJava Observables.
The new version number is 2.0.7.

In this release, I performed mostly internal work not related to the external library API. Nevertheless, it’s important for the library development in the future.

The following things were done:

  • updated dependencies
  • updated Gradle configuration
  • migrated unit tests to Robolectric
  • started executing unit tests on Travis CI
  • added integration with codecov.io and coverage report
  • extracted code related to accessors from the Prefser class (refactoring library internals)

Organizational work is done and now I’m ready for migration to RxJava2 in this project on a separate branch. I want to keep backward compatibility with RxJava1 as in my other projects. This update is planned for version 2.1.0.

Stay tuned!

Joining lists of RxJava Observables

2017-05-15 DSP2017, Java, RxJava No comments

In RxJava we have a few operators for joining Observables. The most common are:

Take a look at the documentation in these links. It has interactive marble diagrams showing how the operators work on the streams. You can move marbles along the lines and see how the output stream changes. It really helps to understand how it works.

Code snippets in this article are based on RxJava 2.1.0 with JUnit 4.12 and Google Truth 0.32 for unit tests.

Let’s say, we have the following Observables:

public Observable<String> emitNumbers() {
  return Observable.fromArray("1", "2", "3", "4").delay(1, TimeUnit.SECONDS);
}

public Observable<String> emitLetters() {
  return Observable.fromArray("a", "b", "c", "d");
}

We can merge them in the different ways.

Concat

Concat operator emits the emissions from two or more Observables without interleaving them.

We can perform the following operation:

public Observable<String> concatStreams() {
  return Observable.concat(emitNumbers(), emitLetters());
}

The easiest way to verify, how this operator works, is to create exploratory unit test as follows:

@Test
public void shouldConcatStreams() {
  // given
  Observable<String> observable = playground.concatStreams();
  List<String> expectedValues = Arrays.asList("1","2","3","4","a","b","c","d");
  List<String> joinedValues = new ArrayList<>();

  // when
  observable.blockingSubscribe(s -> joinedValues.add(s));

  // then
  assertThat(joinedValues).isEqualTo(expectedValues);
}

This operation can be represented graphically as well.

         1 --- 2 --- 3 --- 4
                  |
         a --- b --- c --- d
                  |
                  |
                concat
                  |
                 \|/
1 -- 2 -- 3 -- 4 --- a -- b -- c -- d  

As we can see one stream is appended to another regardless of the execution time of both streams.

Merge

Merge operator combines multiple Observables into one by merging their emissions.

Here we have a similar story, but changed operator:

public Observable<String> mergeStreams() {
  return Observable.merge(emitNumbers(), emitLetters());
}

We are writing another unit test:

@Test
public void shouldMergeStreams() {
  // given
  Observable<String> observable = playground.mergeStreams();
  List<String> expectedValues = Arrays.asList("a","b","c","d","1","2","3","4");
  List<String> joinedValues = new ArrayList<>();

  // when
  observable.blockingSubscribe(s -> joinedValues.add(s));

  // then
  assertThat(joinedValues).isEqualTo(expectedValues);
}

Merge operation should look like that:

         1 --- 2 --- 3 --- 4
                  |
         a --- b --- c --- d
                  |
                  |
                merge
                  |
                 \|/
a -- b -- c -- d --- 1 -- 2 -- 3 -- 4

This operator doesn’t synchronize the streams and merges them as values are emitted. Numbers are emitted later than letters, so letters are placed in the beginning of the output stream. Try to manipulate marble on the interactive diagram on the reactivex.io website to see how it should work.

Zip

The last operator, I’d like to discuss in this article is “Zip” operator. Zip combines the emissions of multiple Observables together via a specified function and emit single items for each combination based on the results of this function.

In simple words, it waits until many observables are emitted and then combines them into a pair (or triple Observable, etc. in the case or more Observables).

Now, we need to create a function, which will transform our streams and return combined stream.

public Observable<String> zipStreams() {
  return Observable.zip(emitNumbers(), emitLetters(),
      (s1, s2) -> String.format("(%s,%s)", s1, s2));
}

Next, we can verify it with test as usual:

@Test
public void shouldZipStreams() {
  // given
  Observable<String> observable = playground.zipStreams();
  List<String> expectedValues = Arrays.asList("(1,a)","(2,b)","(3,c)","(4,d)");
  List<String> joinedValues = new ArrayList<>();

  // when
  observable.blockingSubscribe(s -> joinedValues.add(s));

  // then
  assertThat(joinedValues).isEqualTo(expectedValues);
}

and it can be represented graphically like that:

        1 --- 2 --- 3 --- 4
                 |
        a --- b --- c --- d
                 |
                 |
                zip
                 |
                \|/
 (1,a) -- (2,b) --- (3,c) -- (4,d)

Now, we have pairs of merged streams.

Summary

Of course, RxJava is complicated library and these methods are not covering all possibilities of merging and combining the Observable streams. Neverhteless, examples in this article are quite basic and may help you to understand how mentioned operators work. After that we can apply the best operator to appropriate situation.


Reference thread on StackOverflow: http://stackoverflow.com/questions/28843318/android-rxjava-joining-lists

Analyzing performance of the web application with Chrome Dev Tools

2017-05-15 DSP2017, Performance, Tools, Web Development No comments

Introduction

Recently, I attended a training related to ZK framework. One part of that training was quite interesting for me and was related to measuring and monitoring the performance of the web applications. In Chrome Browser, we have Chrome Dev Tools, which can be opened with Ctrl+Shift+I shortcut or ⌘+Shift+I shortcut on Mac. Inside these tools, we have “Performance” tab. We can hit red “record” icon in the upper left corner of the Tools window and start recording performance of the website while loading it, clicking around or whatever situation we want to monitor. After that, we can see a really nice graph.

This graph presents a performance of our application during the time and shows different metrics divided into the different sections like:

  • Loading
  • Scripting
  • Rendering
  • Painting
  • Other
  • Idle

It can help us to find bottlenecks of the performance and critical sections.

Client-side performance issues

As we can see in this example, “Scripting” takes a lot of time so we can assume that client-side of our application slows down its performance. Moments, where application slowed down are marked with red lines on the main chart. We can select this area and investigate it further.

We could find the exact call of the JavaScript method and now we can try to optimize it in the future.

Server-side performance issues

When “Scripting” doesn’t take most of the time, but an application is still slow, we may suppose, that performance problem is caused by the server-side. In case of Java and JVM application, we can use JVisualVM program to monitor performance of our project. It can be subject of the separate article.

In Chrome Dev Tools, we may also switch to the “Network” tab and mark “XHR” sub-tab, which stands for XML Http Request, which are usually AJAX network calls done via JavaScript to the server.

Next, we can review our request and check, which one is slow. We may also review its header and response.

In the “Timing” tab we can take a look at the execution time of asynchronous connection. If it’s really slow, we may start the further investigation on the server-side in the place where this request is called.

Please note, slow XHR connections may be caused not only by inefficient code on the server-side but also by the infrastructure, servers & networking issues. We should isolate pieces of code & perform unit tests to show that it’s a server-side issue. We can also perform end-to-end tests, measure performance and compute average execution time to conclude what is the real source of the problem.

Summary

As we can see, monitoring performance and finding bottlenecks is not an easy task, but Chrome Dev Tools can help us to fix such issues in a really convenient way.

Short roadmap and plans for my OSS – May 2017

2017-05-14 DSP2017, Open source No comments

As few people might notice, I’m developing a few open-source projects right now. It’s not so easy to manage this stuff when you’re working in a full-time job, doing different not only IT-related things and don’t want to sit in front of the computer all the time. Nevertheless, doing this stuff really helps me to develop my programming & communicating skills and be up to date with various technologies. Instead of searching for excuses, I have the following plans related to releasing updates for my projects in the nearest future:

ReactiveNetwork

  • Review reported issues
  • Verify if reported bugs are real bugs
  • Adjust code to recent RxJava2 features if necessary
  • Handle Walled Garden issue OOTB
  • Add more useful code samples
  • Update existing code samples

Prefser

  • Release decent updates related to project configuration and updating dependencies
  • Migrate project to RxJava2 as a separate artifact
  • Keep backward compatibility with RxJava1 as in ReactiveNetwork project

Others

  • Review projects and their issues
  • Perform new releases in the project with unreleased, but commited changes
  • Handle users’ requests when possible
  • Migrate all RxJava-based projects to RxJava2 while keeping backward compatibility
  • Start new projects (which are currently drafts in my head/notepad/electronic notes/empty private git repos/etc.)

Moreover, I also have plans to learn a few new things not related to my ongoing projects, so that may slow down their development. In addition, I’m going to the conference this week and probably won’t be updating anything at this time. If anyone of you is interested in developing any of my projects, feel free to do it, go ahead and create your PRs! For sure, it will speed up the updates if you’re waiting for any of these.

Emitting different RxJava Observables depending on the condition

2017-05-14 DSP2017, Java, RxJava No comments

Sometimes, we may need to emit different RxJava Observables depending on the specific condition dynamically. Moreover, it’s good to do it right without breaking a chain (stream of Observables). We want to combine different Observables together and do not want to nest one subscription inside another subscription because this will lead us to “subscription hell” similar to “callback hell”. Luckily RxJava has mechanisms to deal with such problems. In this article, I’m basing my examples on RxJava 2.1.0.

Let’s say we have two Observables:

public Observable<String> trueObservable() {
  return Observable.fromCallable(() -> "trueObservable");
}

public Observable<String> falseObservable() {
  return Observable.fromCallable(() -> "falseObservable");
}

and we have another Observable wrapping Boolean value:

public Observable<Boolean> createCondition(boolean returnedValue) {
  return Observable.fromCallable(() -> returnedValue);
}

This Observable can emit true or false depending on the provided parameter.

What we want to do is to:

  • emit trueObservable() when createCondition(boolean) returns true
  • emit falseObservable() when createCondition(boolean) returns false
  • emit falseObservable() when createCondition(boolean) emits empty Observable (default behaviour)

We can do it in the following way:

public Observable<String> emitTrueObservableDynamically() {
  return createCondition(true)
      .defaultIfEmpty(false)
      .flatMap(condition -> condition ? trueObservable() : falseObservable());
}

In such case, this method will emit trueObservable(). When we change parameter of the createCondition(boolean) method to false, Observable will emit falseObservable(). When we replace createCondition(boolean) method with Observable.empty(), method will return falseObservable() by default. As we can see, it’s easily solved with flatMap and defaultIfEmpty operators.

This is quite useful technique, which we can apply to reactive applications to control our flow without breaking the chain. Please note, it’s just an example you can create more complicated constructions and handle more complicated types than just boolean and more than two use cases.


Reference thread for this article on StackOverflow: http://stackoverflow.com/questions/34195218/rxjava-exequte-observable-only-if-first-was-empty.

Basic code refactoring principles

2017-05-05 Code Refactoring, DSP2017, Software Development, TDD, Unit Tests No comments

Introduction

I’ve recently read a book about Test Driven Development by Kent Beck. It’s really good, presents the importance of the TDD and shows how to make a life of the software developer easier. In the TDD we follow red-green-refactor process in which we create a failing unit test, then we fix it and refactor it to make code-base better. There’s no golden rule when to refactor or how to refactor code and each project is different, but there are a few principles we may follow when we want to improve our projects through refactoring.

Finding similarities and duplications

One of the common code smells is duplication. We should search for the following patterns:

  • Two similar loops » try to merge them into one loop
  • Two similar instructions inside conditional statements » try to unify operations and get rid of the “if” statement
  • Two similar methods » try to unify them and remove one of them
  • Two similar classes » try to unify them and remove one of them
  • and so on…

Perform these operations carefully. If something goes wrong, go one step backward. Sometimes it may be impossible to remove all duplications.

Isolating changes

Before we start performing changes, it’s good to isolate a piece of code. We can move it e.g. to separate method, perform changes and then inline our method. That could help us avoid breaking the whole system.

Data migration

If we want to change the meaning of the data, we can temporarily duplicate them, perform changes, update interfaces and then remove original code.

Method extraction

If a method in our class is too big (according to Clean Code, “too big” is longer than 20 lines), we should find code doing specialized mini-task and extract part of it to a separate method. In IntelliJ IDEA we can use Ctrl+Alt+M shortcut or ⌘+Alt+M on Mac for that.

Method inlining

Sometimes, we’re extracting too many pieces of code to separate methods, what may decrease code readability. If the code inside the method is really simple, so it could be written in a single line or optionally in two lines, we may think about inlining this method. To do so, we should remove method and place code directly in the place where it’s called. To perform inlining in IntelliJ, we can use Ctrl+Alt+N shortcut or ⌘+Alt+N on Mac.

Interface extraction

When we want to create additional implementations of the operations, which already exists in our code-base, we may extract these operations into the interface. IntelliJ IDEA also has support for that. I’m not sure if there’s a shortcut, but you can use Ctrl+Shit+A shortcut or ⌘+Shift+A on Mac to open window with operation search and then type “extract interface”. It should work.

Moving method

It may happen, that our class or interface is becoming too big or it has methods, which are not directly related to this class. In such case, we may simply move one method or a few methods to another, more appropriate class or create a separate class or interface for them.

Object-method

We may encounter a situation when a specific method has too many parameters. In such case, we may consider creating Object-method. It’s some kind of data class, which contains attributes the same as method parameters. It will help us to pass data in our system in a more readable way. We can also connect this solution with a Builder software design pattern.

Adding parameter

During the time, the business logic of our system is getting bigger and one of our methods need to be extended. In such case, we can add another parameter to it. We may also consider creating another, similar method with just one more parameter. When we’re providing API or framework for other developers, we have to remember about proper “deprecated” annotations.

Moving parameter from method to the constructor

It may happen that we want to move a parameter from the method to a constructor to simplify the logic of the project. In order to that, we can move local variable to a class variable (in IntelliJ IDEA: Ctrl+Alt+V shortcut or ⌘+Alt+V on Mac) and then create constructor with this variable (Alt+Insert or ⌘+N on Mac).

Summary

As we can see, there are a few principles, which we may apply during code refactoring to make our project better. Moreover, most of them are supported by IntelliJ IDEA, which is great IDE. If you’re programming in another language than Java and want to have refactoring tools, you should check JetBrains products. Nevertheless, there’s no golden rule of refactoring. Sometimes it’s better to leave the code as it is. Especially if code-base is huge, the project is in production and there are no unit tests. If you want to know more about principles from this article, read Test Driven Development book by Kent Beck. Probably there are more principles than these described in this article. We should perform refactoring carefully and we need to remember about tests. Everything depends on the concrete project and our situation.

Monitoring usage of open-source projects

2017-05-05 DSP2017, Open source 2 comments

While developing open-source projects it’s important to monitor usage of them. Having that information we know on which projects we should concentrate the most and which are becoming more popular. In this short article, I’ll present you two tools, which can help you with that.

GitHub

On GitHub, each project has “Traffic” tab. After clicking on it, we can see how many visitors and unique visitors we have, we can also check how many project clones and unique clones were performed (including CI servers). Moreover, we can see referring sites for our projects. It’s useful information because we can check how people gather information about our project.

Sonatype

GitHub stats can be used for any type of project for any language. When we’re developing Java or JVM library and we publish it on SonaType, we can also use oss.sonatype.org website for monitoring usage of our libraries. It provides us quite interesting information, which actually tells us if anyone is using our library.

In the “Central Statistics” section, we can select GroupId and also ArtifactId. We can see accumulated information about downloads of all our projects in time and check, which project is the most popular. We can also view downloads from unique IPs. What I found interesting here is the fact that one of my projects called prefser is quite popular and people really started using it in their projects! Approximately 47% of downloads of all my projects are downloads of that single library. Nevertheless, the last release of this library (v. 2.0.6) was almost one year ago. It encouraged me to put more effort into this project and make it better. I actually started working on it again and planned new releases. Trust of many people is a huge motivation factor & honor for me.

Do you know any more methods of measuring usage of your projects? Maybe for different technologies than Java?

Share your experiences in comments :).