In my current project I'm using MongoDB with Spring .
It's the first time I'm using noSQL database and over all the experience is pretty good.
One of the reasons that required noSQL DB usage was the fact, that various entities can have unknown number of attributes. Furthermore that number can vary depending on the entity internal type.
The Attribute class looks like this:
and AttributeType is a simple enum:
So everything is fine as long we don't have any security concerns. But an Attribute may contain a password information, in that case we would like to use some kind of bi-directional encryption (AES for instance) to encrypt the attribute value before it's being written to the DB and decrypt it right after it's read from the DB.
Since such attributes collections can be member of more than a single class, we need an infrastructural solution.
If we extend AbstractMongoEventListener class we'll achieve a listener that will be called on each one of the following occasions:
for each entity that being saved or retrieved from the DB.
In our case we need to override 2 methods:
To summarize:
Having some kind of general operation on certain entity type, before it's written to MonogDb and\or after it's read from the DB, we can extend AbstractMongoEventListener in order to gain a single location that will allow us to perform such an operation.
Another example that using the technique described above can be found here in Maciej Walkowiak blog
You can see the full code in the gist bellow:
https://gist.github.com/IVedmak/7ec70d6744743a3c30eb
UPDATED:
See gist with complete implementation of the listener that supports more complex data structures and UCs:
1)Attributes collection located in the objects that is deeper than the 1st level
2)The object with attributes collection is a part of the Map object
3)If any of the objects in memory instance used after the encryption and saving it, it's should be decrypted 1st
4)If the same object being referenced by more than one parent object it's should not be encrypted or decrypted twice
If I use an Endpoint entity as an example, it would look like this:
// BaseModel it's a parent class containing a single field // @Id // protected String _id; @Document(collection = "endpoint") public class Endpoint extends BaseModel { private String name; private String description; private String endpointType; private Collectionattributes; // getters and setters }
The Attribute class looks like this:
public class Attributeextends BaseModel { private String parentObjectName; private AttributeType attributeType; private String name; private String displayName; private String fullName; private T value; private T defaultValue; // add getters and setters }
and AttributeType is a simple enum:
public enum AttributeType { STRING,LONG,INTEGER,DATE,DATE_TIME,ENUM,PASSWORD,BOOLEAN,TEXT_AREA; }
So everything is fine as long we don't have any security concerns. But an Attribute may contain a password information, in that case we would like to use some kind of bi-directional encryption (AES for instance) to encrypt the attribute value before it's being written to the DB and decrypt it right after it's read from the DB.
Since such attributes collections can be member of more than a single class, we need an infrastructural solution.
If we extend AbstractMongoEventListener class we'll achieve a listener that will be called on each one of the following occasions:
- onBeforeConvert
- onBeforeSave
- onAfterSave
- onAfterConvert
for each entity that being saved or retrieved from the DB.
In our case we need to override 2 methods:
@Override public void onBeforeConvert(Object source) { super.onBeforeConvert(source); passwordsPersistenceCare(source,true); } //........ @Override public void onAfterConvert(DBObject dbo, Object source) { super.onAfterConvert(dbo, source); passwordsPersistenceCare(source,false); }
To summarize:
Having some kind of general operation on certain entity type, before it's written to MonogDb and\or after it's read from the DB, we can extend AbstractMongoEventListener in order to gain a single location that will allow us to perform such an operation.
Another example that using the technique described above can be found here in Maciej Walkowiak blog
https://gist.github.com/IVedmak/7ec70d6744743a3c30eb
UPDATED:
See gist with complete implementation of the listener that supports more complex data structures and UCs:
1)Attributes collection located in the objects that is deeper than the 1st level
2)The object with attributes collection is a part of the Map object
3)If any of the objects in memory instance used after the encryption and saving it, it's should be decrypted 1st
4)If the same object being referenced by more than one parent object it's should not be encrypted or decrypted twice