Repository navigation
HowTo migration v5 to v6
- Java 21+ (mandatory)
- MongoDB 5.0+ for production deployments
- BSON library: Morphium 6 uses MongoDB's BSON library (version 4.7.1+)
Native SSL/TLS support was introduced in the Morphium driver in v6.0.
Old (v5):
MorphiumConfig cfg = new MorphiumConfig();
cfg.setDatabase("mydb");
cfg.setHosts("localhost:27017");
cfg.setDriverName("PooledDriver");New (v6):
MorphiumConfig cfg = new MorphiumConfig();
cfg.connectionSettings().setDatabase("mydb");
cfg.clusterSettings().addHostToSeed("localhost", 27017);
cfg.driverSettings().setDriverName("PooledDriver");Prefer the new nested settings objects:
-
connectionSettings()- database name, credentials, timeouts -
clusterSettings()- hosts, replica set configuration -
driverSettings()- driver selection and configuration -
messagingSettings()- messaging implementation and settings -
cacheSettings()- caching configuration -
encryptionSettings()- encryption keys
- v5 and v6: select drivers by name via
MorphiumConfig.driverSettings().setDriverName(name). - Built‑in driver names:
-
PooledDriver- Connection-pooled MongoDB driver (default for production) -
SingleMongoConnectDriver- Single-connection driver -
InMemDriver- In-memory driver for testing (no MongoDB required)
-
- Custom drivers must be annotated with
@de.caluga.morphium.annotations.Driver(name = "YourName")to be discoverable.
Old (v5):
Messaging m = new Messaging(morphium, 100, true);
m.setSenderId("myapp");New (v6):
// Use factory method for correct configuration
MorphiumMessaging m = morphium.createMessaging();
m.setSenderId("myapp");
m.start();
m.addListenerForTopic("topic", (mm, msg) -> {
// process message
return null;
});-
Always use
Morphium.createMessaging()so configuration and implementation selection happen correctly - The messaging implementation is chosen by name from
MorphiumConfig.messagingSettings().getMessagingImplementation() - Built-in implementations:
-
StandardMessaging(default) - Single-collection messaging -
MultiCollectionMessaging- Multi-collection messaging for high-volume scenarios
-
- Custom implementations must be annotated with
@de.caluga.morphium.annotations.Messaging(name = "YourName")
In v6, the Msg class field and methods have been renamed from "name" to "topic" to align with standard messaging terminology:
Old (v5):
Msg msg = new Msg("myMessageName", "command", "data");
String name = msg.getName();
msg.setName("newName");New (v6):
Msg msg = new Msg("myTopic", "command", "data");
String topic = msg.getTopic();
msg.setTopic("newTopic");Backward compatibility:
- The MongoDB field is backward compatible via
@Aliases({"name"})annotation - V5 and V6 messaging instances can communicate if
SingleCollectionMessaging(now calledStandardMessaging) is used in V6 - Existing MongoDB documents with the "name" field will continue to work
Removed deprecated methods:
-
getName()→ usegetTopic() -
setName(String)→ usesetTopic(String) -
sendAnswer(Messaging, Msg)→ removed (use messaging instance methods instead)
Morphium v6 changes how null values are handled during serialization and deserialization to be more consistent with MongoDB behavior and other ORMs.
Field missing from MongoDB document:
- Java field is NOT updated (preserves default values or existing values)
- This is consistent behavior regardless of annotations
Field present in MongoDB with explicit null value:
- By default, Java field IS set to null (overwrites default values)
- Use
@IgnoreNullFromDBto protect specific fields from null contamination
Old (v5):
@Entity
public class MyEntity {
private Integer counter = 42; // null from DB would be ignored (protected)
@UseIfnull
private String name; // null from DB would be accepted
}New (v6):
@Entity
public class MyEntity {
private Integer counter = 42; // null from DB IS accepted (becomes null)
@IgnoreNullFromDB
private Integer protectedCounter = 99; // null from DB is ignored (stays 99)
}The @UseIfnull annotation is now deprecated. The behavior has been inverted:
Old behavior (v5):
- Fields WITHOUT
@UseIfnull: ignored nulls from DB (protected) - Fields WITH
@UseIfnull: accepted nulls from DB
New behavior (v6):
- Fields WITHOUT
@IgnoreNullFromDB: accept nulls from DB (standard behavior) - Fields WITH
@IgnoreNullFromDB: ignore nulls from DB (protected)
To migrate:
- Remove
@UseIfnullfrom fields that should accept nulls (this is now the default) - Add
@IgnoreNullFromDBto fields that previously did NOT have@UseIfnullif you want to maintain the old protection behavior
@Entity
public class Example {
private String regularField = "default";
@IgnoreNullFromDB
private String protectedField = "default";
}Scenario 1: MongoDB document is {} (field missing entirely)
-
regularFieldstays "default" -
protectedFieldstays "default"
Scenario 2: MongoDB document is { regularField: null, protectedField: null }
-
regularFieldbecomes null (default overwritten) -
protectedFieldstays "default" (protected from null)
This makes the behavior more consistent: if a field doesn't exist in MongoDB, the Java object is not modified.
In v6, many methods in the Morphium class that perform query-based operations have been marked as deprecated or moved to the Query class. The design principle in Morphium is:
- Morphium class: Entity-based operations (save, delete, updates to specific entities)
- Query class: Query-based operations (reads and updates based on query criteria)
While many methods still exist for backward compatibility, you should migrate to the Query class equivalents.
Deprecated or to-be-removed methods:
-
morphium.set(toSet, collection, values, upsert, callback)- usequery.set() -
morphium.unset(toSet, collection, field, callback)- usequery.unset() -
morphium.inc(fieldsToInc, matching, upsert, multiple, callback)- usequery.inc() -
morphium.push(query, field, value, ...)- usequery.push() -
morphium.pull(entity, field, value, ...)- usequery.pull()
Migration:
Old (v5):
// Setting values on entities matching a query
Map<Enum, Object> values = new HashMap<>();
values.put(MyEntity.Fields.status, "active");
morphium.set(entity, null, values, false, null);
// Unsetting a field
morphium.unset(entity, null, "fieldName", null);
// Incrementing values
Map<Enum, Number> increments = new HashMap<>();
increments.put(MyEntity.Fields.counter, 1);
morphium.inc(increments, query, false, true, null);New (v6):
// Use Query.set() for query-based updates
Query<MyEntity> query = morphium.createQueryFor(MyEntity.class);
query.f("status").eq("pending"); // Query criteria
query.set("status", "active");
// Use Query.unset() for query-based field removal
query.unset("fieldName");
// Use Query.inc() for query-based increments
query.inc(MyEntity.Fields.counter, 1);Note: Entity-based operations remain in Morphium:
-
morphium.setInEntity(entity, collection, values, ...)- updates a specific entity -
morphium.unsetInEntity(entity, collection, field, ...)- unsets field in a specific entity -
morphium.store(entity)- saves/updates a specific entity
Use Query methods when updating based on query criteria, use Morphium methods when updating a specific entity instance.
Removed methods:
-
createQueryFor(Class, String collectionName)- two-parameter version removed -
createQueryByTemplate(T template, String... fields)- template-based queries removed -
findByTemplate(T template, String... fields)- template-based find removed
Migration:
Old (v5):
// Creating query with custom collection name
Query<MyEntity> query = morphium.createQueryFor(MyEntity.class, "custom_collection");
// Template-based queries
MyEntity template = new MyEntity();
template.setStatus("active");
List<MyEntity> results = morphium.findByTemplate(template, "status");New (v6):
// Use single-parameter createQueryFor and specify collection on query
Query<MyEntity> query = morphium.createQueryFor(MyEntity.class);
query.setCollectionName("custom_collection");
// Template-based queries: use standard query syntax
Query<MyEntity> query = morphium.createQueryFor(MyEntity.class);
query.f("status").eq("active");
List<MyEntity> results = query.asList();Read operations:
-
readAll(Class)- deprecated (usecreateQueryFor(Class).asList()) -
findByField(Class, field, value)- deprecated (use query with field filter) -
findById(Class, id, collection)- three-parameter version deprecated
Index operations:
-
ensureIndex(Class, callback, Enum... fields)- deprecated (useensureIndices(Class)) -
getIndexesFromMongo(Class)- deprecated (use driver-specific methods)
Other operations:
-
flush(Class)- deprecated (use buffered writer methods directly) -
createAggregator(Class, resultClass)- exists (supported) -
mapReduce(Class, map, reduce)- exists (supported, but MongoDB deprecated it)
Migration approach:
- Replace
morphium.set/unset/inc/push/pullwith equivalentquery.set/unset/inc/push/pullmethods - Use
Queryfor all update operations instead of directMorphiummethods - Use standard query syntax instead of template-based queries
- For simple operations like
findById, usequery.f(Query.ID_FIELD).eq(id).get()
The InMemoryDriver received major enhancements in v6.1:
- Full change stream support with document snapshots
- Proper event isolation preventing dirty reads
- Database-scoped driver sharing with reference counting
- Multiple Morphium instances can share the same InMemoryDriver when using the same database name
// Multiple messaging instances can now share InMemoryDriver correctly
MorphiumMessaging msg1 = morphium1.createMessaging();
MorphiumMessaging msg2 = morphium2.createMessaging();
// Both will receive change stream events from the shared driver- No replica set simulation (single-instance only)
- No sharding support
- Limited geospatial operations compared to MongoDB
- See
docs/howtos/inmemory-driver.mdfor detailed feature coverage
Morphium 6 targets Java 21+ throughout. Virtual threads were tried for change-stream event
dispatching and messaging but rolled back in 6.2.x (JDK 21's synchronized pinning caused
deadlocks under load); those paths run on platform threads today. Async operation handling
(Morphium's async API) still uses a virtual-thread pool.
- URI-based configuration:
MONGODB_URIenvironment variable - System properties:
-Dmorphium.driver=inmem - Properties file:
morphium-test.properties
- Tag-based test organization (
@Tag("core"),@Tag("messaging"),@Tag("inmemory")) - Improved test runner:
./runtests.shwith retry logic and filtering - Better isolation between tests with proper driver lifecycle management
- Update to Java 21+
- Update pom.xml dependency to
6.1.1or higher - Replace flat config setters with nested settings objects
- Change messaging instantiation to
morphium.createMessaging() - Update messaging code: replace
getName()/setName()withgetTopic()/setTopic() - Replace removed
Morphiummethods:-
morphium.set/unset/inc()→ usequery.set/unset/inc()instead -
morphium.findByTemplate()→ use standard query syntax -
morphium.readAll()→ usequery.asList() -
morphium.findByField()→ use query with field filter -
morphium.createQueryFor(Class, collection)→ usequery.setCollectionName()
-
- Review null handling behavior: consider adding
@IgnoreNullFromDBto fields that need protection from null values - Remove deprecated
@UseIfnullannotations (behavior is now inverted) - Review custom driver/messaging implementations for annotation requirements
- Update test infrastructure to use tags if using parameterized tests
- Test with InMemoryDriver to verify change stream handling
- The JMS classes provided are experimental/incomplete and should not be relied upon for full JMS compatibility
- May be completed in upcoming versions
- Check
docs/troubleshooting-guide.mdfor common issues - Review
docs/howtos/for specific use cases - Join our Slack: https://join.slack.com/t/team-morphium/shared_invite/...