Skip to content
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
25 changes: 25 additions & 0 deletions jackson-modules/jackson-conversions-3/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,27 @@
<artifactId>json</artifactId>
<version>${json.version}</version>
</dependency>
<dependency>
<groupId>org.mongojack</groupId>
<artifactId>mongojack</artifactId>
<version>${mongojack.version}</version>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-sync</artifactId>
<version>${mongodb-driver.version}</version>
</dependency>
<dependency>
<groupId>de.undercouch</groupId>
<artifactId>bson4jackson</artifactId>
<version>${bson4jackson.version}</version>
</dependency>
<dependency>
<groupId>de.flapdoodle.embed</groupId>
<artifactId>de.flapdoodle.embed.mongo</artifactId>
<version>${flapdoodle.version}</version>
<scope>test</scope>
</dependency>
</dependencies>

<build>
Expand All @@ -57,6 +78,10 @@
<properties>
<mockserver-netty.version>5.13.2</mockserver-netty.version>
<json.version>20240303</json.version>
<mongojack.version>5.0.3</mongojack.version>
<mongodb-driver.version>5.6.1</mongodb-driver.version>
<bson4jackson.version>2.18.0</bson4jackson.version>
<flapdoodle.version>4.21.0</flapdoodle.version>
</properties>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.baeldung.jackson.pojomapping;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import de.undercouch.bson4jackson.BsonFactory;
import org.bson.BsonBinaryWriter;
import org.bson.BsonDocument;
import org.bson.Document;
import org.bson.RawBsonDocument;
import org.bson.codecs.BsonDocumentCodec;
import org.bson.codecs.EncoderContext;
import org.bson.io.BasicOutputBuffer;

import java.io.IOException;

public class BsonProductMapper {

private final ObjectMapper objectMapper;

public BsonProductMapper() {
this.objectMapper = new ObjectMapper(new BsonFactory());
}

public byte[] toBytes(Product product) throws JsonProcessingException {
return objectMapper.writeValueAsBytes(product);
}

public Product fromBytes(byte[] bson) throws IOException {
return objectMapper.readValue(bson, Product.class);
}

public Document toDocument(Product product) throws IOException {
byte[] bytes = toBytes(product);
RawBsonDocument bsonDoc = new RawBsonDocument(bytes);
return Document.parse(bsonDoc.toJson());
}

public Product fromDocument(Document document) throws IOException {
BsonDocument bsonDoc = document.toBsonDocument();
BasicOutputBuffer buffer = new BasicOutputBuffer();
new BsonDocumentCodec().encode(
new BsonBinaryWriter(buffer),
bsonDoc,
EncoderContext.builder().build()
);
return fromBytes(buffer.toByteArray());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.baeldung.jackson.pojomapping;

import org.mongojack.Id;
import org.mongojack.ObjectId;

public class Product {

@ObjectId
@Id
private String id;
private String name;
private double price;

public Product() {
}

public Product(String name, double price) {
this.name = name;
this.price = price;
}

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

public String getName() {
return name;
}

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

public double getPrice() {
return price;
}

public void setPrice(double price) {
this.price = price;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.baeldung.jackson.pojomapping;

import com.mongodb.client.MongoDatabase;
import org.bson.UuidRepresentation;
import org.mongojack.JacksonMongoCollection;

public class ProductService {

private final JacksonMongoCollection<Product> collection;

public ProductService(MongoDatabase database) {
this.collection = JacksonMongoCollection.builder()
.build(database, "products", Product.class, UuidRepresentation.STANDARD);
}

public void save(Product product) {
collection.insertOne(product);
}

public Product findById(String id) {
return collection.findOneById(id);
}

public long count() {
return collection.countDocuments();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package com.baeldung.jackson.pojomapping;

import org.bson.Document;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.io.IOException;

import static org.junit.jupiter.api.Assertions.*;

class BsonProductMapperUnitTest {

private BsonProductMapper mapper;
private Product product;

@BeforeEach
void setUp() {
mapper = new BsonProductMapper();
product = new Product("Test Product", 29.99);
}

@Test
void whenSerializingProduct_thenReturnsByteArray() throws IOException {
byte[] bytes = mapper.toBytes(product);

assertNotNull(bytes);
assertTrue(bytes.length > 0);
}

@Test
void givenSerializedProduct_whenDeserializing_thenReturnsProduct() throws IOException {
byte[] bytes = mapper.toBytes(product);

Product deserializedProduct = mapper.fromBytes(bytes);

assertEquals(product.getName(), deserializedProduct.getName());
assertEquals(product.getPrice(), deserializedProduct.getPrice(), 0.01);
}

@Test
void whenConvertingProductToDocument_thenReturnsValidDocument() throws IOException {
Document document = mapper.toDocument(product);

assertNotNull(document);
assertEquals(product.getName(), document.getString("name"));
assertEquals(product.getPrice(), document.getDouble("price"), 0.01);
}

@Test
void whenRoundTrippingProduct_thenDataIsPreserved() throws IOException {
Document document = mapper.toDocument(product);
Product roundTrippedProduct = mapper.fromDocument(document);

assertEquals(product.getName(), roundTrippedProduct.getName());
assertEquals(product.getPrice(), roundTrippedProduct.getPrice(), 0.01);
}

@Test
void givenDocument_whenConvertingToProduct_thenReturnsProduct() throws IOException {
Document document = new Document()
.append("name", "Document Product")
.append("price", 49.99);

Product convertedProduct = mapper.fromDocument(document);

assertEquals("Document Product", convertedProduct.getName());
assertEquals(49.99, convertedProduct.getPrice(), 0.01);
}

@Test
void givenProductWithNullFields_whenSerializing_thenHandlesGracefully() throws IOException {

Product productWithNulls = new Product();
productWithNulls.setPrice(10.0);

byte[] bytes = mapper.toBytes(productWithNulls);
Product deserializedProduct = mapper.fromBytes(bytes);

assertNull(deserializedProduct.getName());
assertEquals(10.0, deserializedProduct.getPrice(), 0.01);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package com.baeldung.jackson.pojomapping;

import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import de.flapdoodle.embed.mongo.distribution.Version;
import de.flapdoodle.embed.mongo.transitions.Mongod;
import de.flapdoodle.embed.mongo.transitions.RunningMongodProcess;
import de.flapdoodle.reverse.TransitionWalker;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.*;

class ProductServiceLiveTest {

private TransitionWalker.ReachedState<RunningMongodProcess> mongodbProcess;
private MongoClient mongoClient;
private ProductService productService;

@BeforeEach
void setUp() {
mongodbProcess = Mongod.instance().start(Version.Main.V5_0);
var serverAddress = mongodbProcess.current().getServerAddress();

mongoClient = MongoClients.create(String.format("mongodb://%s:%d",
serverAddress.getHost(), serverAddress.getPort()));
productService = new ProductService(mongoClient.getDatabase("testdb"));
}

@AfterEach
void tearDown() {
if (mongoClient != null) {
mongoClient.close();
}
if (mongodbProcess != null) {
mongodbProcess.close();
}
}

@Test
void whenSavingProduct_thenProductIsPersisted() {
Product product = new Product("Laptop", 999.99);

productService.save(product);

assertNotNull(product.getId());
assertEquals(1, productService.count());
}

@Test
void whenSavingProductWithAllFields_thenAllFieldsArePersisted() {
Product product = new Product("Full Product", 199.99);

productService.save(product);
Product foundProduct = productService.findById(product.getId());

assertNotNull(foundProduct.getId());
assertEquals("Full Product", foundProduct.getName());
assertEquals(199.99, foundProduct.getPrice(), 0.01);
}
}