Android, Development, Java, Kotlin

How to debug an Annotation Processor in Android Studio

Writing an Annotation Processor in Java/Kotlin is a very interesting task and debugging comes very handy, but unfortunately it seems not so easy to start a debug session.

rubber ducks

The following information are valid for Android Studio 3.6.3 and Kotlin 1.3.71. Gradle is the build tool used for the project.

First thing to do is setup a new Run/Debug Configuration in Android Studio:

  • Choose Run from the main menu
  • Choose Edit Configurations
  • Now click on the + symbol in the top left corner to add a new Configuration
  • Choose Remote from the list
  • Give it a friendly name (e.g. AnnotationProcessorDebugger)

Setup your breakpoints wherever you need them and then run this command from the terminal:

./gradlew --no-daemon -Dorg.gradle.debug=true :APP_MODULE_NAME:clean :APP_MODULE_NAME:compileDebugJavaWithJavac

Replace APP_MODULE_NAME with the name of the module having annotations which you want to debug. You will see the process will start and suddenly stop on > Starting Daemon waiting for you to do something.

Now, click on the Debug icon in the Toolbar (having selected the previously created AnnotationProcessorDebugger configuration) and the debugger will hit your breakpoints!

Additional info:

The clean task seems to be necessary.

Unfortunately, sometimes these steps are not enough, or simply don’t work, the debugger won’t hit your breakpoints. I see somebody else solved the issue after adding the following line to their gradle.properties file.

kapt.use.worker.api=true
Development, Java, Spring

Using Spring Data to persist a Set of Enums in a Many-To-Many relationship

Usually, when we write a Many-To-Many relationship it is between 2 entities. Sometimes, it could happen that we have an entity which has a field which is a set of enum. In this case, we need to approach the problem differently and Spring comes to help.

Let’s see an example where we have two classes: Person and Skill (e.g. swimming, running, etc).

Many-To-Many between entities example

The following code shows what the situation is when Person and Skill are both entities.

@Entity
public class Person {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;
  private String name;
  @ManyToMany(fetch = FetchType.LAZY)
  @JoinTable(name = "person_skill", joinColumns = {
            @JoinColumn(name = "person_id")}, inverseJoinColumns = {
            @JoinColumn(name = "skill_id")})
  private Set<Skill> skillSet;
}

@Entity
public class Skill {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;
  private String name;
}

To use this mapping, you would have 3 tables. You can create them with the following SQL code.

CREATE TABLE `person` (
  `id` BIGINT(20) NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(45) NOT NULL,
  PRIMARY KEY (`id`));

CREATE TABLE `skill` (
  `id` BIGINT(20) NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(45) NOT NULL,
  PRIMARY KEY (`id`));

CREATE TABLE `person_skill` (
  `person_id` BIGINT(20) NOT NULL,
  `skill_id` BIGINT(20) NOT NULL,
  PRIMARY KEY (`person_id`, `skill_id`),
  INDEX `skill_fk_idx` (`skill_id` ASC),
  CONSTRAINT `person_fk`
    FOREIGN KEY (`person_id`)
    REFERENCES `person` (`id`)
    ON DELETE CASCADE
    ON UPDATE CASCADE,
  CONSTRAINT `skill_fk`
    FOREIGN KEY (`skill_id`)
    REFERENCES `skill` (`id`)
    ON DELETE CASCADE
    ON UPDATE CASCADE);

Many-To-Many between entity and enum example

The following code shows what the situation is when Person is an entity and Skill is an enum.

@Entity
public class Person { 
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id; 
  private String name; 
  @ElementCollection(targetClass = Skill.class)
  @CollectionTable(name = "person_skill",
            joinColumns = @JoinColumn(name = "person_id"))
  @Enumerated(EnumType.STRING)
  @Column(name = "skill_name")
  private Set<Skill> skillSet;
} 

public enum Skill {
  RUNNING, SWIMMING
}

To use this mapping, you would have only 2 tables, because Skill is not an entity and would not have its own table. You can create them with the following SQL code.

CREATE TABLE `person` (
  `id` BIGINT(20) NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(45) NOT NULL,
  PRIMARY KEY (`id`));

CREATE TABLE `person_skill` (
  `person_id` BIGINT(20) NOT NULL,
  `skill_name` VARCHAR(45) NOT NULL,
  PRIMARY KEY (`person_id`, `skill_name`),
  CONSTRAINT `person_fk`
    FOREIGN KEY (`person_id`)
    REFERENCES `person` (`id`)
    ON DELETE CASCADE
    ON UPDATE CASCADE);

As you can see here, you don’t have the table skill because Skill is not an entity but only an enum; you only have to create the table which represents the relationship between Person and Skill. Furthermore, since we added the annotation @Enumerated(EnumType.STRING) Spring Data will save the name of the entity in the database (look, we put a VARCHAR column). If you prefer, you could use EnumType.ORDINAL and Spring Data will save the ordinal value of the entity (1,2,3,etc..), so change the column to accept a numeric value.

That’s it!

Development, Java

Java concurrency: a few examples

Sometimes we write very high level code, sometimes we don’t. I want to put here a link to a simple project which shows how to deal with concurrency in Java with a few examples.

The project is available on Github here

Goal of the project is to retrieve the details and the balance of a player and show them at the same time: until you have collected both of them you have to wait before showing the user the information.

There are two different packages: in the first, Futures and Callables are being used, in the other, Threads/Runnables and a CountDownLatch are.

Futures and Callables are the best option when you need to run a task which has a return value. I also made it in a different way using Threads/Runnables, a CountDownLatch and some listeners but these classes are usually used when you have tasks which won’t return any value.

Use the two Main classes to run the examples. Have fun!