Skip to content

update quickstart with lombok and enum example #242

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: q320
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
Note: when upgrading the Quarkus version or the DataStax Java driver version, make sure that you
upgrade them in the quickstart module too.
-->
<quarkus.version>3.2.4.Final</quarkus.version>
<quarkus.version>3.4.0.CR1</quarkus.version>
<datastax-java-driver.version>4.17.0</datastax-java-driver.version>
<assertj.version>3.23.1</assertj.version>
<maven.compiler.target>11</maven.compiler.target>
Expand Down
65 changes: 46 additions & 19 deletions quickstart/README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ First, let's create our data model – represented by the `Fruit` class – as f

[source,java]
----
@Data
@Entity
@PropertyStrategy(mutable = false)
public class Fruit {
Expand All @@ -84,12 +85,12 @@ public class Fruit {
private final String name;

private final String description;
private final Type type;

public Fruit(String name, String description) {
this.name = name;
this.description = description;
public enum Type {
LOCAL,
DELIVERED
}
// getters, hashCode, equals, toString methods omitted for brevity
}
----

Expand All @@ -105,6 +106,29 @@ class name: `fruit`.
Also, the `name` field represents a Cassandra partition key, and so we are annotating it with
`@PartitionKey` – another annotation from the Object Mapper library.

Also, we use here `@Data` annotation from Lombok that allow us not to write manually getter/setter
and other boilerplate code. And as you can see one field has Enum type that is not supported by
cassandra. To handle it we should register our own `TypeCodec`

We perform it when app is ready in next way:
[source,java]
----
@ApplicationScoped
public class AppLifecycleBeanCodecRegistration {

@Inject CqlSession session;

void onStart(@Observes StartupEvent ev) {
TypeCodec<Fruit.Type> myEnumCodec = new EnumNameCodec<>(Fruit.Type.class);

MutableCodecRegistry registry = (MutableCodecRegistry) session.getContext().getCodecRegistry();
registry.register(myEnumCodec);
}
}
----
So we subscribe on `StartupEvent` and add to CodecRegistry our <String, Enum> codec that
automatically convert Enum to TEXT and vise versa.

IMPORTANT: Entity classes are normally required to have a default no-arg constructor, unless they
are annotated with `@PropertyStrategy(mutable = false)`, which is the case here.

Expand Down Expand Up @@ -174,18 +198,23 @@ The Object Mapper is composed of 2 pieces:

Therefore, enabling the Object Mapper requires two steps:

1. Declare the `cassandra-quarkus-mapper-processor` annotation processor. With Maven, this is done
by modifying the compiler plugin configuration in the project's `pom.xml` file as follows:
1. Declare the `lombok` and the `cassandra-quarkus-mapper-processor` annotation processor (order is important).
With Maven, this is done by modifying the compiler plugin configuration in the project's `pom.xml` file as follows:

[source,xml]
----
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.10.1</version>
<version>${compiler-plugin.version}</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</path>
<path>
<groupId>com.datastax.oss.quarkus</groupId>
<artifactId>cassandra-quarkus-mapper-processor</artifactId>
Expand All @@ -200,6 +229,8 @@ With Gradle, this is done by adding the following line to the `build.gradle` fil

[source,groovy]
----
annotationProcessor "org.projectlombok:lombok:${lombok.version}"

annotationProcessor "com.datastax.oss.quarkus:cassandra-quarkus-mapper-processor:${cassandra-quarkus.version}"
----

Expand Down Expand Up @@ -292,11 +323,12 @@ public class FruitResource {
}

private FruitDto convertToDto(Fruit fruit) {
return new FruitDto(fruit.getName(), fruit.getDescription());
return new FruitDto(fruit.getName(), fruit.getDescription(), fruit.getType().name());
}

private Fruit convertFromDto(FruitDto fruitDto) {
return new Fruit(fruitDto.getName(), fruitDto.getDescription());
Fruit.Type type = Fruit.Type.valueOf(fruitDto.getType());
return new Fruit(fruitDto.getName(), fruitDto.getDescription(), type);
}
}
----
Expand All @@ -306,23 +338,18 @@ Notice how `FruitResource` is being injected a `FruitService` instance automatic
It is generally not recommended using the same entity object between the REST API and the data
access layer. These layers should indeed be decoupled and use distinct APIs in order to allow each
API to evolve independently of the other. This is the reason why our REST API is using a different
object: the `FruitDto` class – the word DTO stands for "Data Transfer Object". This DTO object will
be automatically converted to and from JSON in HTTP messages:
object: the `FruitDto` class – the word DTO stands for "Data Transfer Object". It's annotated by
`@Data` that allow us not to write boilerplate code. This DTO object will be automatically
converted to and from JSON in HTTP messages:

[source,java]
----
@Data
public class FruitDto {

private String name;
private String description;

public FruitDto() {}

public FruitDto(String name, String description) {
this.name = name;
this.description = description;
}
// getters and setters omitted for brevity
private String type;
}
----

Expand Down
36 changes: 27 additions & 9 deletions quickstart/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,25 +27,31 @@
<inceptionYear>2020</inceptionYear>
<properties>
<java.version>11</java.version>
<quarkus.version>3.2.4.Final</quarkus.version>
<quarkus.platform.version>3.4.0.CR1</quarkus.platform.version>
<quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-id>
<quarkus.platform.group-id>io.quarkus.platform</quarkus.platform.group-id>
<datastax-java-driver.version>4.17.0</datastax-java-driver.version>
<lombok.version>1.18.28</lombok.version>
<assertj.version>3.23.1</assertj.version>
<compiler-plugin.version>3.11.0</compiler-plugin.version>
<surefire-plugin.version>3.0.0</surefire-plugin.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<failsafe.testGroups>!native</failsafe.testGroups>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-bom</artifactId>
<version>${quarkus.version}</version>
<groupId>${quarkus.platform.group-id}</groupId>
<artifactId>${quarkus.platform.artifact-id}</artifactId>
<version>${quarkus.platform.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.datastax.oss.quarkus</groupId>
<artifactId>cassandra-quarkus-bom</artifactId>
<!-- for your project use here latest release version-->
<version>${project.version}</version>
<type>pom</type>
<scope>import</scope>
Expand Down Expand Up @@ -90,6 +96,12 @@
<groupId>io.quarkus</groupId>
<artifactId>quarkus-micrometer-registry-prometheus</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5</artifactId>
Expand Down Expand Up @@ -147,22 +159,28 @@
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.10.1</version>
<version>${compiler-plugin.version}</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</path>
<path>
<groupId>com.datastax.oss.quarkus</groupId>
<artifactId>cassandra-quarkus-mapper-processor</artifactId>
<!-- for your project use here latest release version-->
<version>${project.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M7</version>
<version>${surefire-plugin.version}</version>
<configuration>
<systemProperties>
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
Expand All @@ -171,7 +189,7 @@
</plugin>
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<version>3.0.0-M7</version>
<version>${surefire-plugin.version}</version>
<executions>
<execution>
<goals>
Expand All @@ -189,9 +207,9 @@
</configuration>
</plugin>
<plugin>
<groupId>io.quarkus</groupId>
<groupId>${quarkus.platform.group-id}</groupId>
<artifactId>quarkus-maven-plugin</artifactId>
<version>${quarkus.version}</version>
<version>${quarkus.platform.version}</version>
<executions>
<execution>
<goals>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.datastax.oss.quarkus.demo;

import com.datastax.oss.driver.api.core.CqlSession;
import com.datastax.oss.driver.api.core.type.codec.TypeCodec;
import com.datastax.oss.driver.api.core.type.codec.registry.MutableCodecRegistry;
import com.datastax.oss.driver.internal.core.type.codec.extras.enums.EnumNameCodec;
import io.quarkus.runtime.StartupEvent;
import io.smallrye.config.Priorities;
import jakarta.annotation.Priority;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.event.Observes;
import jakarta.inject.Inject;

@ApplicationScoped
public class AppLifecycleBeanCodecRegistration {

@Inject CqlSession session;

void onStart(@Observes @Priority(Priorities.PLATFORM - 10) StartupEvent ev) {
TypeCodec<Fruit.Type> myEnumCodec = new EnumNameCodec<>(Fruit.Type.class);

MutableCodecRegistry registry = (MutableCodecRegistry) session.getContext().getCodecRegistry();
registry.register(myEnumCodec);
}
}
42 changes: 6 additions & 36 deletions quickstart/src/main/java/com/datastax/oss/quarkus/demo/Fruit.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
import com.datastax.oss.driver.api.mapper.annotations.Entity;
import com.datastax.oss.driver.api.mapper.annotations.PartitionKey;
import com.datastax.oss.driver.api.mapper.annotations.PropertyStrategy;
import java.util.Objects;
import lombok.Data;

/**
* Represents the name and description of a fruit.
Expand All @@ -27,48 +27,18 @@
* href="https://docs.datastax.com/en/developer/java-driver/latest/manual/mapper/entities/">Defining
* entities with the DataStax Java driver object mapper</a>
*/
@Data
@Entity
@PropertyStrategy(mutable = false)
public class Fruit {

@PartitionKey private final String name;

private final String description;
private final Type type;

public Fruit(String name, String description) {
this.name = name;
this.description = description;
}

/**
* @return The fruit name.
*/
public String getName() {
return name;
}

/**
* @return The fruit description.
*/
public String getDescription() {
return description;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Fruit that = (Fruit) o;
return Objects.equals(description, that.description) && Objects.equals(name, that.name);
}

@Override
public int hashCode() {
return Objects.hash(description, name);
}

@Override
public String toString() {
return String.format("Fruit{name='%s', description='%s'}", name, description);
public enum Type {
LOCAL,
DELIVERED
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,50 +15,17 @@
*/
package com.datastax.oss.quarkus.demo;

import java.util.Objects;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/** A DTO (Data Transfer Object) used to convey information from a {@link Fruit} domain object. */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class FruitDto {

private String name;
private String description;

public FruitDto() {}

public FruitDto(String name, String description) {
this.name = name;
this.description = description;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getDescription() {
return description;
}

public void setDescription(String description) {
this.description = description;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

FruitDto fruitDto = (FruitDto) o;

if (!Objects.equals(name, fruitDto.name)) return false;
return Objects.equals(description, fruitDto.description);
}

@Override
public int hashCode() {
return Objects.hash(description, name);
}
private String type;
}
Loading