Skip to content

Configure camel casing for Chronicle and MongoDB

This how-to shows how to get camelCase field names in your read-model documents, the same for the documents Chronicle projections write and the documents Arc reads and writes in MongoDB.

Store read-model data with camelCase field names, and keep Chronicle and Arc’s MongoDB integration agreeing on every field and collection name.

Two things decide the stored names:

  • The declared member names. C# properties are PascalCase by convention; Kotlin properties, Java record components and TypeScript fields are already camelCase.
  • The naming policy. A naming policy can rename members and collections on the way to MongoDB. Chronicle’s projections and Arc’s MongoDB integration each apply one, and both must agree, or Arc reads fields and collections that Chronicle never writes.
  • An application using Arc with its MongoDB integration, and Chronicle for projections.
  • For C#, the Cratis meta package setup (AddCratis() and UseCratis()).

Each backend does what its conventions call for:

var builder = WebApplication.CreateBuilder(args);
builder.AddCratis(
configureArcBuilder: arcBuilder => arcBuilder.WithMongoDB(
configureMongoDB: mongoBuilder => mongoBuilder.WithCamelCaseNamingPolicy()),
configureChronicleBuilder: chronicleBuilder => chronicleBuilder.WithCamelCaseNamingPolicy());
var app = builder.Build();
app.UseCratis();
await app.RunAsync();

View C# snippet source on GitHub

Turn on the camel case naming policy in both places: in Arc’s MongoDB integration and in the Chronicle client.

Field names need no configuration. Documents store each property under its declared name, which is already camelCase, and the Chronicle JVM client has no camel case option.

Collection names need no configuration either. With Arc’s MongoDB integration and the Chronicle starter both on the classpath, Arc’s naming policy also names the collection Chronicle projects each read model into, so a projected User lands in Users, the collection Arc reads. This needs Chronicle.Kotlin 6.10.0 or later, which adds the read-model naming policy Arc supplies. To choose other names, declare your own Arc NamingPolicy bean (it flows through the same way), or a Chronicle ReadModelNamingPolicy bean to name Chronicle’s collections alone. An application that declares its own ChronicleOptions bean sets the policy itself with withReadModelNamingPolicy.

Field names are already camelCase, and Chronicle’s TypeScript client writes them as declared. Set camelCaseMongoNamingPolicy on withMongoDB when your read models must match a C# service that uses camel case: it also camel-cases collection names (User becomes users).

Collection names follow Arc. When withMongoDB is configured, the Chronicle client Arc creates stores each projected read model listed in readModels in the collection Arc reads it from (users with camelCaseMongoNamingPolicy), so no collectionName override is needed. This needs @cratis/chronicle 6.29.0 or later, which adds the read-model naming policy Arc supplies. A read model Arc does not read keeps its identifier as the collection name. If you pass your own client to withChronicle, Arc leaves it alone: set readModelNamingPolicy on its ChronicleOptions yourself.

withMongoDB’s database must match the event store name, because Chronicle writes the default namespace’s read models to a database named after the event store.

With this setup:

  • Chronicle projections write read-model fields in camelCase.
  • Arc’s MongoDB integration reads and writes the same camelCase field names.
  • A property declared as EmailAddress in C#, or emailAddress in Kotlin, Java or TypeScript, is stored as emailAddress.

After your app runs and projections update read models, inspect the stored documents. You should see camelCase fields. If a query returns empty or half-filled read models, compare the stored collection and field names with the names your backend expects; a naming mismatch produces no error.