Overriding Getters and Setters in tinkerpop Frames annotated model - orientdb

I'm working on a new piece of software and I'd like the values in the database to be encrypted. We are using OrientDB and are trying to implement the project using the tinkerpop libraries. Here I'm stuck a little bit.
For one function, I need to pull a list of all vertices of a type and return them. I have my annotated interface for the person object, and I added methods to encrypt and decrypt necessary fields right now. But when I decrypt them, it persists the decrypted values back to the database.
Is there a way to either override the getters and setters to handle the encryption/decryption at that point or do I need to detach the models from the db before performing my decryption?
Here's my code for my interface:
public interface iPerson {
#Property("firstName")
public void setFirstName(String firstName);
#Property("firstName")
public String getFirstName();
#Property("lastName")
public String getLastName();
#Property("lastName")
public void setLastName(String lastName);
#Property("id")
public String getId();
#Property("id")
public void setId(String id);
#Property("dateOfBirth")
public String getDateOfBirth();
#Property("dateOfBirth")
public void setDateOfBirth(String dateOfBirth);
#JavaHandler
public void encryptFields() throws Exception;
#JavaHandler
public void decryptFields() throws Exception;
public abstract class Impl implements JavaHandlerContext<Vertex>, iPerson {
#Initializer
public void init() {
//This will be called when a new framed element is added to the graph.
setFirstName("");
setLastName("");
setDateOfBirth("01-01-1900");
setPK_Person("-1");
}
/**
* shortcut method to make the class encrypt all of the fields that should be encrypted for data storage
* #throws Exception
*/
public void encryptFields() throws Exception {
setLastName(Crypto.encryptHex(getLastName()));
setFirstName(Crypto.encryptHex(getFirstName()));
if(getDateOfBirth() != null) {
setDateOfBirth(Crypto.encryptHex(getDateOfBirth()));
}
}
/**
* shortcut method to make the class decrypt all of the fields that should be decrypted for data display and return
* #throws Exception
*/
public void decryptFields() throws Exception {
setLastName(Crypto.decryptHex(getLastName()));
setFirstName(Crypto.decryptHex(getFirstName()));
if(getDateOfBirth() != null) {
setDateOfBirth(Crypto.decryptHex(getDateOfBirth()));
}
}
}
}

(I assume) Data is persisted to the database when a Vertex's property is set. If you want to store encrypted values in the database, then you need to ensure the value is encrypted when the property is set.
If you want to override the default behaviour of the #Property getter/setter methods (so that you can add en/decryption), I'd recommend using a custom handler (e.g. #JavaHandler).
For example:
IPerson
#JavaHandlerClass(Person.class)
public interface IPerson extends VertexFrame {
#JavaHandler
public void setFirstName(String firstName);
#JavaHandler
public String getFirstName();
}
Person
abstract class Person implements JavaHandlerContext<Vertex>, IPerson {
#Override
void setFirstName(String firstName) {
asVertex().setProperty('firstName', encrypt(firstName))
}
#Override
String getFirstName() {
return decrypt(asVertex().getProperty('firstName'))
}
static String encrypt(String plain){
return plain.toUpperCase(); // <- your own implementation here
}
static String decrypt(Object encrypted){
return encrypted.toString().toLowerCase(); // <- your own implementation here
}
}
Usage example (Groovy)
// setup
IPerson nickg = framedGraph.addVertex('PID1', IPerson)
IPerson jspriggs = framedGraph.addVertex('PID2', IPerson)
nickg.setFirstName('nickg')
jspriggs.setFirstName('jspriggs')
// re-retrieve from Frame vertices sometime later...
IPerson nickg2 = framedGraph.getVertex(nickg.asVertex().id, IPerson)
IPerson jspriggs2 = framedGraph.getVertex(jspriggs.asVertex().id, IPerson)
// check encrypted values (these are stored in the DB)...
assert nickg2.asVertex().getProperty('firstName') == 'NICKG'
assert jspriggs2.asVertex().getProperty('firstName') == 'JSPRIGGS'
// check decrypted getters...
assert nickg2.getFirstName() == 'nickg'
assert jspriggs2.getFirstName() == 'jspriggs'
If using Groovy, you could intercept calls to these methods programatically (which would be nice because you could keep using #Property annotations).
I'm not sure if there's a Tinkerpop solution to intercepting these calls, other than writing your own custom handler (maybe try extending the JavaHandlerModule?).

Thanks for the comment, and I should have gotten back to respond to this sooner, but I recently found a better answer to my problem. I was looking for a way to make the encrypt/decrypt happen without overhead and without developers really noticing it happens.
The better way to tackle this issue was actually to write hooks for before insert/update and after read to handle it just at the database layer. I was able to write it in java, package a jar file for it and install it on our orientDB instance, picked up pretty flawlessly and helped us to encrypt the necessary fields without noticing any speed decreases.

Related

Could you explain me one OOP confusion?

I am creating a program for testing a website. Site has a registration process, which I am testing.
I have created a class named "Client", which should store the information about the client (name, family name, e-mail etc.).
Since I am testing, I use random number generator to generate a name for the client (I have the list of names, one of which is chosen randomly).
Obviously, I should create a method "generateName ()".
But the question is: in which class I should create it?
Lots of programmers would create the method in the Client class. And would do something like that:
client = new Client ();
client.generateName ();
But I have read, that this approach is incorrect - because the client does not generate name for himself. Program does.
Based on that information, I do as follows:
class Program
{
private void generateName ();
}
...
class Client
{
...
public void name ( String name )
{
this.name = name;
}
}
program = new Program ();
program.launch();
client = new Client ();
client.name ( program.generateName () );
But as I know, this approach is not used by the developers.
Could you clarify, how to know "what is right and what is wrong" here? And what information source should I use as an arbitrary for the cases of this kind?
It sounds like generateName() could be a static method in Client, since it's independent of instances:
class Client {
private String name;
public Client(String name) {
this.name = name;
}
public static String generateRandomName() {
String generatedName = ...;
return generatedName;
}
}
You could the simply pass it's value to the Client object as you currently are, or via the constructor:
client = new Client(Client.generateRandomName());
Otherwise, I'd suggest a ClientNameGenerator to handle name generation, to keep inline with SRP and to raise cohesion. This would be the better choice, seeing how you may be needing more name generation methods in the future:
class ClientNameGenerator {
public String generateRandomName() {
String generatedName = ...;
return generatedName;
}
//other name generation methods...
}
You can now use a ClientNameGenerator object to manage the generation of client names:
ClientNameGenerator nameGenerator = new ClientNameGenerator();
client = new Client(nameGenerator.generateRandomName());
Anytime you need to generate a name, simply use the ClientNameGenerator object you created.
There are a number of places which might be appropriate locations for this functionality.
You could have it as a private method on the Client class, used by a static factory method for generating Clients with a random name.
public class Client {
....
public static Client randomlyNamed() {
return new Client(randomName());
}
private static String randomName() {
return ...;
}
}
But that private method might be better extracted to a more appropriate class for generating random Strings...
public class Client {
private static final int defaultNameLength = 8;
....
public static Client randomlyNamed() {
return new Client(Strings.randomString(defaultNameLength));
}
}
public class Strings
private static String randomString(int length) {
return ...;
}
}
You could then expand the static method into a general purpose ClientBuilder class, with an instance method named something like 'withRandomName()'.
public class Client {
...
}
public class ClientBuilder {
private static final int defaultNameLength = 8;
...
public ClientBuilder randomlyNamed() {
this.name = Strings.randomString(defaultNameLength);
}
public Client build() {
return new Client(name);
}
}
public class Strings
private static String randomString(int length) {
return ...;
}
}
An alternative would be an implementation of a NamingStrategy (e.g. ``) object which is given to a ClientBuilder object.
public class RandomNames implements NamingStrategy {
private static final int defaultNameLength = 8;
public String name() {
return String.randomString(defaultNameLength);
}
}
public class ClientBuilder {
private final NamingStrategy nameSource;
public ClientBuilder(NamingStrategy nameSource) {
this.nameSource = nameSource;
}
public Client build() {
return new Client(nameSource.name());
}
}
The pure way to go would be to have a separate class ClientGenerator that produces clients. Because generating clients is not typical client behavior and in your application model a client is no more than a passive data container for client properties. However, generating clients is an activity in "the client domain". Therefor it would be defendable to create a static method Client.NewClient(), like the .NET feamework does with Guid. On the other hand, a guid's very nature is to be generated, it does not represent something in the real world. It IS a spawnable id. So the comparison may not be all that ligitimate.
A common similar mistake (or impurity if you wish) is a Save method on an object. Instead one should have a Persister class that does the job. Or a Manager. Because Save is something you can do to or with the class, not behavior of the class ifself.

Eclipselink Integrity Checker

I'm using EclipseLink and I'd like to check whether entity and table definitions are consistent.
I found "Integrity Checker" and tried it.
public final class EMF {
public static class EnableIntegrityChecker implements SessionCustomizer {
#Override
public void customize(Session session) throws Exception {
session.getIntegrityChecker().checkDatabase();
session.getIntegrityChecker().setShouldCatchExceptions(false);
}
}
private static final EntityManagerFactory INSTANCE;
static {
String appId = SystemProperty.applicationId.get();
Map<String, String> overWriteParam = new HashMap<>();
overWriteParam.put(
PersistenceUnitProperties.SESSION_CUSTOMIZER,
EnableIntegrityChecker.class.getName());
INSTANCE = Persistence.createEntityManagerFactory("unit", overWriteParam);
}
private EMF() {
}
public static EntityManager create() {
return INSTANCE.createEntityManager();
}
}
Some cases it can detect inconsistency, but some cases can not.
If entity has variable A and table does not have column A, Integrity Checker can found inconsistency.
If table has colume A and entity does not have variable A, Integrity Checker can not found inconsistency.
If column A in table is int and variable A in entity is String, Integrity Checker can not found inconsistency.
How can I detect inconsistency in case 2 and 3?
You can extend IntegrityChecker, override it's checkTable method and use it via session.setIntegrityChecker(customIntegrityChecker). Note that some of validations are located in ClassDecriptor#checkDatabase so it's hard to directly re-use them and properly report exact error cause.

Service Class + Instantiating new classes

I wanted to know if this was thread safe/ good practice. My IOC is ninject, everything service layer call is via the default setting (In transient scope I think?).
Question, is instantiating new FileAllocation(loggedonuser,_repo) correct? The best way? What is the best way to do this? This is a domain class that holds logic that could be called from various services, there are usually a few database calls involved, most of the time no persistance is necessary...
Anyway, I call my service method via an interface e.g.
void SaveFile(int reportid, stream file); //Interface name: IReportFileService
public Class FileService: Servicebase, IReportFileService
{
private readonly IRepoSession _repo;
public FileService(IUserSession user, IRepoSession repo, IUpdateSession update)
: base(user,update)
{
_repo = repo;
}
//save file if users 'counter' is ok..
public void SaveFile(int reportid, stream file)
{
//here I want to instantiate a new class that I store in my domain and store the counters
//etc and do related db calls to check up relevant values
//note loggedonuser is a prop on my *base class*
var userChecks = new FileAllocation(loggedonuser,_repo);
userChecks.CountEmUp(); //exception is thrown if 0, less than "limit" etc...
base.update(userChecks.mycompany); //persist
base.commit(); //base class method includes try, catch block...
}
}
public class FileAllocation
{
private readonly IRepoSession _repo;
private readonly Loggedonuser _user;
private int CompanyUploads;
private int UserUploads;
public Company mycompany;
public FileAllocation(Loggedonuser user, IRepoSession repo)
{
_repo = repo;
_user = user;
}
public void CountEmUp()
{
//do error checking,
//load up other tables can user upload - permissions, count is ok etc...
// check the upload type if of certain type we cannot proceed - call another method on this class
//set myCompany variable to new limits etc...
}
}
Base Service includes a prop, I dont want to instantiate this from other services i.e. more that once, how do I avoid that?
private LoggedonuserDTO _currentuser = null;
protected LoggedonuserDTO loggedonuser
{
get
{
if (_currentuser == null)
{
_currentuser = _user.GetCurrentUser(); //make db call here...
}
return _currentuser;
}
}
#Darin suggested:
public interface IFileAllocation
{
CountEmUp(Loggedonuser currentuser);
}
//pass in loggedonuser to any method that requires it...
public class FileAllocation: IFileAllocation
{
CountEmUp(Loggedonuser currentuser)
{
//do whatever here...
}
}
var userChecks = new FileAllocation(loggedonuser,_repo);
introduces a strong coupling between the FileService and the FileAllocation classes. If this is not a problem for you then you can leave it that way. Otherwise you could abstract the operations of this FileAllocation class into an interface and then inject it into FileService. This way the FileService is weakly coupled with FileAllocation and could be reused in different contexts and unit tested in isolation.

Deserialization of ArrayList GWT

In my application I'm getting some data from a file located in the server. The data is stored in a text file (.obj), so I'm using an rpc to read the file and get the data. The file is read using a third party library http://www.pixelnerve.com/processing/libraries/objimport/ I'm sending the data to the client using ArrayLists, basicly I'm sending this: ArrayList[ArrayList[Vertex3dDTO]] where Vertex3dDTO is an serializable object with contains float parameters. ArrayList[Vertex3dDTO] is contained in another serializable class Face3dDTO, and ArrayList[Face3dDTO] is in the serializable class Group3dDTO.
package com.nyquicksale.tailorapp.shared;
import java.io.Serializable;
public class Vertex3dDTO implements Serializable {
float x,y,z;
public Vertex3dDTO(){
}
public Vertex3dDTO(float x, float y, float z){
this.x = x;
this.y = y;
this.z = z;
}
}
public class Face3dDTO implements Serializable {
ArrayList<Vertex3dDTO> vL = new ArrayList<Vertex3dDTO>();
Vertex3dDTO normal = new Vertex3dDTO();
Vertex3dDTO color = new Vertex3dDTO();
public Face3dDTO(){
}
public Face3dDTO(ArrayList<Vertex3dDTO> v) {
for(Vertex3dDTO v3dDTO : v){
vL.add(v3dDTO);
}
updateNormal();
}
public class Group3dDTO implements Serializable {
ArrayList<Face3dDTO> fL = new ArrayList<Face3dDTO>();
String name;
public Group3dDTO(){
}
public Group3dDTO(ArrayList<Face3dDTO> f) {
for(Face3dDTO f3dDTO : f){
fL.add(f3dDTO);
}
}
}
Now, everything is working well in development mode, but when I tested the application in hosted mode, everything I receive as response is: //OK[0,1, ["java.util.ArrayList/4159755760"],0,7]
So, I've been checked some other questions and seems the problem is about deserialization, but I've not found anything concrete.
The question is what do I have to do to get the app working well in hosted mode?
To successfully use RPC, your object needs to implement Serializable and should also have a default no arg constructor
Have you made sure this is a serialization problem? You can write a simple RPC test method to pass an array list of your DTO's over the wire in hosted mode.
If I were to bet money on a guess, I would say the problem is those array lists are sent empty in hosted mode. The .obj file read could be the problem. Perhaps in hosted mode the path of file doesn't match as in dev mode(different server configurations perhaps?), since file operations are in a try catch block an exception is most likely swallowed.
Long word short, Did you make sure those array lists are not sent empty in hosted mode?
Your object may well be Serializable, but that doesn't equate to something usable by Remote Procedure Calls. You need to implement Serializable, have a default contructor with no arguments (that calls super() if necessary), and a serial version ID, like so:
public class MyObject implements Serializable {
/**
*
*/
private static final long serialVersionUID = -1796729355279100558L;
private Float someValue;
public MyObject() {
super();
}
public MyObject(Float someValue) {
super();
this.someValue = someValue;
}
public Float getSomeValue() {
return someValue;
}
public void setSomeValue(Float someValue) {
this.someValue = someValue;
}
}

How to access multiple resources in a single request : Jersey Rest

I am trying to a find a good design for the following scenario.
I have a POST rest service which will be given an array of services as data. And which should in turn be calling them one by one to aggregate results on the server and send them back to the client.
#Path("/resource1")
#Path("/resource2")
#Path("/collection")
Post data to /collection
{["serviceName": "resource1", "data":"test1"], ["serviceName":"resource2","data":"test2"]}
The reason i need the resource1 and resource2 are, because those services can be called standalone also. I want to reuse the same setup if possible.
Is there any way to do this.
I am using jersey with spring.
Not sure what these resources have in common. If the post method has the same signature for all of them, you could have an abstract class or interface they implement defining the post method and can try using ResourceContext.matchResource to do this. E.g. something like this:
public abstract class AbstractResource {
public abstract String post(Object data);
}
#Path("/resource1")
public class Resource1 extends AbstractResource {
#POST
public String post(String data) {
// do something
}
}
#Path("/collection")
public class CollectionResource {
#Context
private ResourceContext rc;
#POST
#Consumes("application/json")
public String post(List<PostRequest> postRequests) {
StringBuilder result = new StringBuilder();
for (PostRequest pr : postRequests) {
// should wrap this in try-catch
AbstractResource ar = rc.matchResource(pr.resource,
AbstractResource.class);
sb.append(ar.post(pr.data));
}
return result.toString();
}
}
#XmlRootElement
public class PostRequest {
public String resource;
public String data;
}
Hopefully you got the idea and will be able to play with it and tweak it to fit your needs.