I am writing a Java Spring Boot (servlet) web-API application. There are repository classes in the application. Repository methods are written "from scratch" using Google Cloud Datastore API looking like this:
@Override
public User save(User user) {
try {
// Datastore specific code to populate the user entity
// to then save it into the database
Entity entity = ...
datastore.put(entity);
} catch (DatastoreException datastoreException) {
String errorMessage = messageSource.getMessage(
"persistence.datastore.failed_to_save",
new Object[]{User.KIND}, // where User.KIND is "User" string
LocaleContextHolder.getLocale());
throw new DatastorePersistenceException(errorMessage, datastoreException);
}
return user;
}
I wrap database communication code into try catch. When google.DatastoreException occurs I catch it and then create new project-local DatastorePersistenceException exception, populate it with error message and actual google's exception and then throw this new populatd DatastorePersistenceException further.
The problem
I want to avoid hardcoded string literals with the exception specific message. Instead I want to utilize messages.properties to get the exact message string by key: persistence.datastore.failed_to_save=Failed to save {} in Datastore. I also want to keep it short and use the same message key and pattern for all DatastorePersistenceExceptions so I am using string interpolation.
The problem is that string interpolation requires the following code that allocates memory in new Object[]{User.KIND}:
} catch (DatastoreException datastoreException) {
String errorMessage = messageSource.getMessage(
"persistence.datastore.failed_to_save",
new Object[]{User.KIND},
LocaleContextHolder.getLocale());
throw new DatastorePersistenceException(errorMessage, datastoreException);
}
where messageSource is private final MessageSource messageSource;.
Why I think this is a problem
- memory allocations should be avoided in
catchblocks as they can lead to memory allocation failures.
What am I looking for
- avoid memory allocation in
catchblock and still utilize string interpolation.
P.S. At the same time there is new DatastorePersistenceException... thrown that involves memory allocation in catch block. But this is a working pattern if you want to have higher level of abstraction leaving database vendor's specific exception class incapsulated. Is new DatastorePersistenceException also a "risky" practice in the sense of memory allocation in catch block?