Environment setup

Pre-requisites:

  • JDK 7 or later installed

  • Maven 3.5.2 or later installed

  • Git 2.15.1 or later installed

Eclipse

The Kill Bill projects can be imported into the Eclipse IDE as long as the m2e plugin is installed. Recent versions of the Eclipse IDE for Java EE Developers come with this plugin already.

Some of the Maven plugins used may not be available to m2e, however, and the projects will not import completely. To work around this issue, the Eclipse Preferences > Maven > Lifecycle Mappings configuration can be updated to include mappings like the following:

<?xml version="1.0" encoding="UTF-8"?>
<lifecycleMappingMetadata>
 <pluginExecutions>
   <pluginExecution>
     <pluginExecutionFilter>
       <groupId>org.apache.maven.plugins</groupId>
       <artifactId>maven-antrun-plugin</artifactId>
       <versionRange>1.4</versionRange>
       <goals>
         <goal>run</goal>
       </goals>
     </pluginExecutionFilter>
     <action>
       <execute>
         <runOnConfiguration>true</runOnConfiguration>
         <runOnIncremental>true</runOnIncremental>
       </execute>
     </action>
   </pluginExecution>
   <pluginExecution>
     <pluginExecutionFilter>
       <groupId>org.codehaus.mojo</groupId>
       <artifactId>templating-maven-plugin</artifactId>
       <versionRange>1.0-alpha-3</versionRange>
       <goals>
         <goal>filter-sources</goal>
       </goals>
     </pluginExecutionFilter>
     <action>
       <execute>
         <runOnConfiguration>true</runOnConfiguration>
         <runOnIncremental>true</runOnIncremental>
       </execute>
     </action>
   </pluginExecution>
   <pluginExecution>
     <pluginExecutionFilter>
       <groupId>org.codehaus.mojo</groupId>
       <artifactId>build-helper-maven-plugin</artifactId>
       <versionRange>[1.0,)</versionRange>
       <goals>
         <goal>add-source</goal>
         <goal>add-test-source</goal>
         <goal>add-resource</goal>
         <goal>add-test-resource</goal>
         <goal>maven-version</goal>
         <goal>parse-version</goal>
       </goals>
     </pluginExecutionFilter>
     <action>
       <execute>
         <runOnConfiguration>true</runOnConfiguration>
         <runOnIncremental>true</runOnIncremental>
       </execute>
     </action>
   </pluginExecution>
 </pluginExecutions>
</lifecycleMappingMetadata>

Build

Kill Bill is a standard Maven project. Simply run the following command from the project root directory:

mvn clean install -DskipTests

On the first build, Maven will download all the dependencies from the internet and cache them in the local repository (~/.m2/repository), which can take a considerable amount of time. Subsequent builds will be faster.

Once built, you can start Kill Bill by running:

./bin/start-server -s

PostgreSQL

By default, Kill Bill will expect a MySQL database. To switch to PostgreSQL:

  • Create a killbill user and database (verify connectivity with psql -h 127.0.0.1 -U killbill -p 5432):

create USER killbill;
\password killbill;
CREATE DATABASE killbill WITH OWNER killbill;
  • Create the schema:

./bin/db-helper -a create  --driver postgres -u killbill -p killbill
  • Modify the profiles/killbill/src/main/resources/killbill-server.properties:

org.killbill.dao.url=jdbc:postgresql://127.0.0.1:5432/killbill
org.killbill.dao.user=killbill
org.killbill.dao.password=killbill

org.killbill.billing.osgi.dao.url=jdbc:postgresql://127.0.0.1:5432/killbill
org.killbill.billing.osgi.dao.user=killbill
org.killbill.billing.osgi.dao.password=killbill

Dependencies

The base pom.xml (org.kill-bill.billing:killbill-oss-parent) defines all of the dependencies required by Kill Bill. If a -SNAPSHOT version is specified (e.g. 0.141.74-SNAPSHOT), this means some dependencies haven’t been released yet and you need to build them locally, before being able to build Kill Bill.

Typically, the following repositories need to be built in order:

Navigating the Kill Bill codebase

It can be quite daunting to start poking around the Kill Bill codebase, as the code is scattered over various repositories. Here is a primer on how to get started.

Core system

The following blog posts can help provide more context on the Kill Bill architecture:

Ecosystem

Date, Time and Timezone

A few general concepts around time in Kill Bill:

  • Kill Bill’s granularity is the day, and as a result the system will not invoice for portions of a day.

  • Each account in Kill Bill has a default timezone and that timezone is used throughout the system to be able to convert a DateTime into a Date into the account Timezone.

  • Kill Bill will internally use UTC for all its Datetime manipulation, but any Date information is interpreted as a Date in the account timezone.

Mysql Date, DateTime, Timestamp

We are only relying on date and datetime which are not sensitive to the MySQL timezone setting:

  • Datetime: Storing a Datetime value into MySQL relies on datetime which is independent of the mysql time_zone. It is stored as a UTC value, and the selected value is always the same, regardless of the MySQL timezone.

  • LocalDate: Storing a LocalDate value into MySQL relies on date which is also independent of the MySQL time_zone.

System Configuration

From an operation point of view, there are different places where timezone may be set:

  1. Server on which Kill Bill runs

  2. JVM setting

  3. Database server

It is required to have Kill Bill runs in UTC for correct serialization of DateTime/LocalDate. Actually, in Java, there is no UTC timezone setting but instead GMT. In a first approximation, we will consider those identical, even though they are not and could lead to some rare issues.

When Kill Bill starts, it will override the default timezone if this one was specified as a system property with something different than GMT. The code will log a WARN message and proceed to do so, to avoid issues later down the road.

REST APIs

Kill Bill APIs that accept dates as an argument will allow for the following:

  • A fully qualified Datetime (a point in time)

  • A Date

If there is a need to convert from a Datetime to a Date, the conversion will occur by specifying the account timezone, so the resulting Date is as seen by the customer. This would for instance be the case when triggering a future invoice by specifying a target Datetime.

If there is a need to convert from a Date to Datetime, this is obviously more subtle as we can’t infer the additional precision to compute the time. The Date is always interpreted to be a Date as seen by the customer, that is in the account timezone.

The system will use the reference time on the account in such a way that converting back from that fully qualified Datetime using the account timezone would give us back the original Date provided.

Multiple changes in a day

So what happens if a user is making several subscription changes within the same day?

In the default mode, Kill Bill will react to changes immediately and trigger a new invoice for each change, which in turn might result in a charge.

Let’s consider the following case, where there exists 3 monthly plans (Bronze, Silver and Gold), ordered by ascending price:

  • Initially, the customer is invoiced for the Bronze, from january 1st to feb 1st. By default a payment would also be made.

  • On January 1st again, the customer changes its mind and moves to Silver. A new invoice is generated that will credit the full month — including the day of january 1st — and the new plan is now invoiced from january 1st to february 1st and the credit generated is immediately used, so in the end the customer is really only invoiced for the difference of the price between the 2 plans; Additionally, a new payment is made for that amount.

  • If now the customer changes its plan on Jan 2nd, the portion from January 1st to January 2nd will be invoiced for the Silver plan and the portion from January 2nd to February 1st will be invoiced for the Gold plan.

From an entitlement point of view, the system will reflect the current plan and therefore two different calls to retrieve the plan information on January 1st may lead to different results since there was a change of plan during that day.