Expressing Audit functionality with JPA annotations - java

I'm in the middle of fumbling around with JPA. I've so far successfully created an entity representing the user data and a stateless bean for the access to the user data.
The data the users can work on is like this (SQLFiddle link):
CREATE TABLE data
(
email character varying(128) NOT NULL,
data character varying(128) NOT NULL,
lastchange timestamp NOT NULL,
CONSTRAINT email_data PRIMARY KEY (email,data)
);
The idea is to save the unaltered, current version for all users with an empty email key. Then, when a user alters the data and creates an auditable version, the email field is filled with the users email. This way, each user can alter their copy of the data. The merging is a problem for a later date and not part of my question.
Now, I have the entities already in place. I created a stateless bean to load/save/find the data records by using the EntityManager. The logic to load the user specific version first, then load the unaltered version if the user has no user specific version still eludes me.
Consider this part of the bean:
#Stateless
public class DataBean {
#PersistenceContext(unitName = "authPU")
private EntityManager em;
public List<DataEntry> findAll() {
TypedQuery<DataEntry> query = em.createQuery("SELECT d FROM data d", DataEntry.class);
List<DataEntry> list = query.getResultList();
return query.getResultList();
}
...
}
How do I inject the user information into this class? I need to get the data for the current user first, then get the data for all users if there's no user-specific data available.

You could use standard EJB authentication. Then you can call SessionContext.getCallerPrincipal() in your session bean to get a user ID. Use this user ID to query the database.
In this case you have to add another column to your table (containing the user ID), if the authentication user ID does not equal the email address.
Far simpler (but less elegant) is to add the email address to the arguments of your EJB service method: Just make it part of the public API.

Related

Query through all provided schemas

I have kind of 'restaurant app' with multi tenant architecture. Each Tenant in short words have their Order table where I keep all data regarding orders which were made.
I also have a User/Client table which is in public schema, cause each Client can make order in different restaurants (tenants).
Problem: The problem which came in my implementation is that I'd like to display to the client all orders that he made.
Question: How can I query through all (or provided) Tenants to query such data?
Current CurrentTenantIdentifierResolver looks like:
public String resolveCurrentTenantIdentifier() {
return Optional
.ofNullable(TenantContext.getTenantSchema())
.orElse(PUBLIC_TENANT);
}
Whenever a user visits a tenant (Restaurant), you will be storing the Tenant's (AKA Restaurants) id that the user is in now as part of UserTenants or some other table like this.
When a consolidated orders list is required, you can run a query in the above table to get the list of all tenants (Restaurants) that the user has been to and then for each of the tenant, setup the context for the tenant (the one that helps setup the schema in the datasource) and you should be able to pull the data.
You can run the queries in parallel across all the tenant schema and then concatenate them all to get the full list of orders.

Mapping single bean class to multiple tables in hibernate

I have developed a spring rest service which will accepts a json input and freeze the details in to database and return the status as json output. everything is working fine.
now i need to update the service with the new requirement, i will get address details of the user and i need to update the address table as well. My question is
1) How to change the input request currently my controller is as follows
#Requestmappping(value="/register", metod=RequestMethod.POST)
public #ResponseBody ResponseEntity userRegis(#RequestBody UserBean userdetails){
}
2) How to change the UserBean format. Currently it is mapping to one single table. Now i need to update the bean with address fields. and i need to map the address fields to new table.
please help on this.
What you are referring to in composition in OOP. So, basically user has address or addresses.
class User {
....
private Address addres;
//private List<Address> addres; use something like this if user has multiple addesses
}
class Address {
}
And offcourse you would not want to map same bean to multiple tables or something like that. The above relation is simple parent child relation. Read here

Spring mulitple rows with hibernate bean

We are migrating to spring & hibernate from struts1.x and JDBC.
Facing issue while adding multiple rows in jsp (like mapped properties in struts1.x) based on user preferences (Ex: Adding/deleting employees to Manager) in spring.
In service layer, getting Manager Object (as persistent object returned by hibernate )then displaying manager object in JSP. Employee row will be deleted by using java script/jquery from html form by user delete action, upon form submission spring does not delete in the respective employee from the list of employees of Manager object (model attribute). I have worked on some examples without hibernate where the object is being deleted from the list and works well but not in the hibernate prepared object.
ex: lets say Manager object have 3 employees as List when displaying on screen, when user will delete one employee row and submitted then spring needs to populate the Manager object with two employee objects as list since one employee is deleted by user in UI.
I suspect that, this behavior with PersistentBag implementation of Hibernate?
Anybody experienced this problem earlier? Any ideas would be greatly appreciate.
It might depends on how the pojo is declared..
Sure you are deleting a manager, but how is the manager connected to the employee?
If on the manager you have a Employee Object, you should have
#OneToOne(cascade=CascadeType.ALL, orphanRemoval=true, fetch=FetchType.EAGER)
#Fetch(FetchMode.SUBSELECT)
#JoinColumn(name="EMPLOYEE_ID", nullable = false)
private Employee employee;
This way, if you delete the manager object, it will cascade delete the Employee object...
Either your "cascade" is enforced via db, or it must be enforced via annotation.. if you're not doing either, of course nothing will happen...

EJB Session Bean / Client Hibernate Session interaction?

in a school project we are using an EJB Session Bean,
this EJB offers simple services such as add, delete, modify, findAll, findbyId. Such methods are implemented using hibernate 4.0 (add -> saveOrUpdate, modify -> saveOrUpdate...) and are available for the client
I have two classes : Game (id, description, category) and Category (id, title).
A category has also a set of games.
The ids are generated using the identity generator. The databased used is mysql.
In the client
A form is used by the application user to fill out informations about a game (description and category ) In the controller I use the method findById to get the category that the user chose, then I create a new game with this category and I save it (using SaveOrUpdate)
first problem that I notice : the id is generated correctly in the EJB and the game passed is modified but back in the client the game doesn't have an id (I guess passing objects between a client and a EJB is not by reference) Can anyone confirm it ?
second problem : when the game is save I tried to add this game to the set of the category and update this category (using also saveOrUpdate). I get the exception org.hibernate.NonUniqueObjectException:
a different object with the same identifier value was already associated with the session
which I don't understand
Can anyone help me ?
For the first question, it sounds like the ID isn't being sent back to the client, or being stored with the controller .
You could send it back to the client by adding it to the URL, ie, in the return from the client call add "?id=" + newGameId
With this you can have the value populate back into the controller with setters and getters for an id field;
long id;

Update object properties

I'm using Struts 2, my problem is that I don't want to update all my object properties because I got some sensitive data.
Here is my code example
public class person {
private name;
private email;
private password;
}
In my form for example I display the name and email for update ,so when I update my person properties after submission ,the password property of the person gets the value null,but when I put the property password in the <s:hidden> tag in the form the update works fine.
How to make Struts 2 remember the value of the password without using the hidden tag in the form ?
If you need to store informations that
must be persistent across the requests;
must not be shown in the page;
then you have to use the Session, by implementing SessionAware:
That said, I'm not sure you should store the user password, nor associate passwords to users;
You should make a login page in your web application, handling the password in that Action only, validating it against the database (or whatever), and storing some authentication id in the Session, not the password itself (you won't validate the user again, unless the session expires, then the user will be redirected to login page... no need to keep the password in memory).
That said too, the best practices for user authentication discourage to validate entered passwords against stored passwords on database;
you should use some one-way hashing algorithm (adding a salt to prevent Rainbow Tables attacks) to hash a password, and checking it against the hashed password on the database. This way, not even the database administrator could know the passwords of the users, and in case of a forgotten password, it will be resetted, not retrieved.
In Java one of the best implementations out there is jBCrypt, based on BCrypt.
Hope that helps...
EDIT
As a way to conceptually separate the objects you handle in your Web Application, you can use two different beans: a "Full Bean" for reading, with all the properties, and a "Subset Bean" for writing, containing only the properties that could change.
For example, ID and Password should not change... you could read from Database the "Full", and write to the JSP and then to database the "Subset" (except that in user registration, where you will write the full)...
To make it more understandable, the Full Bean is the Dao Object mapping exactly the database fields, while the Subset Bean is a Presentation Object, that you will create by copying only the desired attributes from the Dao Object... they're both DTOs, but with two different levels of semantic.
Otherwise just put in session your bean, it is one row of code, and you will be ok.
You can check "null"(or a unique value) value at server-side (If it is null, it means : There is no change.) .
or you can use this class for update request
Public class person
{
protected name;
protected email;
}
Public class personNew: person // inherit from person
{
private password;
}
I dont use "Struts 2", but in my Web-app(APS.NET C#). I go on this way

Categories

Resources