#Version Spring dont work with ObjectForm - java

I use #Version in one Java class and all Java classes extends of this. okey.
I also use objectForm. I use this because it is assumed that is more secure (I hide all <form:hidden path="XX"/> from JSP), but when I open two tabs in my browser, if I modify and safe the object in the two tabs, Spring does not check that the version is lower than that of the database and save it. If I not use object form, Spring alert me that the version is lower. Yes, objectForm is obligatory.
The idea is: I send ObjectForm at JSP. I modify the object from jsp and then, I return object form to controller. This, convert the objectForm to object and save the object.
Any idea?
Some pictures:

The #Version annotation only works in Hibernate entity classes, that are directly saved into the database.
If you do the following the #Version will be validated, throwing an exception if an object with an invalid version is attempted to be saved in the database:
read an entity from the database annotated with #Version
copy entity data to a view layer object (including the version)
modify it on the view layer
on save button pressed, copy the form data including the version to a new entity object
to save the new data, call entityManager.merge()
the merge will trigger a database selection. if the version in the database is higher than the merged object you will get a StaleObjectException

Related

Persist new parent entity only if linked entity already exist in the database with JPA

I have an entity Video that needs to be written to a database with Java/Hibernate. Each video can have one or more tags. Currently, there are only certain tags that can be used (predefined and managed in another place).
Videos can be edited and created via REST API.
Now, I want to persist a new Video with tags into the database, but there should be no persist if one or more tags do not already exist in the database.
My first idea would be to query each tag before the persist if it exists in the database and fail with the first match.
But I think there are many unnecessary queries and I would like to know if there is something easier I can use.
You can check the corresponding tags before saving record to the database in your service method as shown below (you might update it to check multiple tags):
public void create(FileRequest request) {
if (tagRepository.existsByNameIgnoreCase(request.getTagName())) {
throw new ElementAlreadyExistsException("File with same tag already exists");
}
// save file
}

How can I get the oldObject at any point of time?

Let say I have the following POJO
public class Plan{
private Long id;
private String name;
//other fields,getters, builder..
}
Now let say there is some Plan which already exist in db.
Now I am trying to modify/update various fields of this particular Plan by using the restAPI(api/v1/Plan/123).
Now we use Jackson here,so I will get the updated Plan object.I will be validating this updated Plan object and if all good will persist in the db.
Till here there is no issue.
But we using an internal service to audit this,i.e what all details got modified in this particular Plan and done by whom at what time etc.
For ex:Plan name changed from (Plan1 to Plan2)
Internal service will accept argument as (oldPlan,newPlan).
Now how can I get the oldPlan from the newPlan object?[Since the file which I have now got the method as public Plan update(Plan newPlan),inside this method only we will be calling an internal service method which requires oldPlan]
Constraints:
1.I should not fire the query getting the id from the newPlan,since that will be duplicate query coz it was already queried when creating newPlan object using jackson.
2.I should not change the update method signature and in update method the plan object which we receive via argument is the object which got updated details in it.
What I have in my mind is:
a)Having the Plan object itself in the POJO ,so that when I get newPlan.getPlan() will return the oldInstance?
The above approach can be done but I am not sure abt this.Whats the best approach to achieve this?

Spring data mongodb interface configuration and use of _class field

I'm migrating from MySQL to mongodb and wondering about couple of things:
1> when using JpaRepository interface and MySQL i need to provide configuration(in my case in the form of settings in application.properties) for it to work otherwise the application fails with a message saying configuration of DataSource failed... but with MongoRepository the application works without any sort of configuration and the data is saved to the default test db. I'd like to know how and where spring makes the initial configuration of the Driver , db name, user and password to use.
2> All objects saved through MongoRepository contain an additional _class field with FQN of the object,
in section 4.6.2 Type mapping the docs say that it needs to do that because
the values held inside that property have to be read in correctly when retrieving the object.
which i didnt fully understand and would love an elaboration on. i created a test with User collection and a few documents in it, some with _class and some without(by inserting the objects using the mongoshell) and the test application had no problem retrieving the User objects that didnt have the _class field and printing them to the console. I also changed the _class field for the collections that had it to "" and it still printed them correctly so how does Spring uses it?

How do I apply a projection to a Spring Data REST query method resource?

I'm using Spring Data REST 2.1.4.RELEASE.
I created
an entity Booking,
its REST repository (extending CrudRepository) named BookingRepository
and a projection BookingDetails (annotated with #Projection(name="details", types = Booking.class)) for returning some of its linked entities exploded, such as Resource, Activity, Applicant etc.
The client gets all bookings with .../rest/bookings and the JSON response includes links for the linked entities. If it adds ?projection=details then the linked entities are exploded and returned. And this is great.
Now I add this custom method to the repository:
List<Booking> findByApplicant(#Param("applicant") Person applicant);
When the client invokes it with .../rest/bookings/search/findByApplicant?applicant=5, there seem to be no way to request the details projection. Following attempts are ignored:
adding &projection=details to the query string
making the method always return BookingDetails:
List<BookingDetails> findByApplicant(#Param("applicant") Person applicant);
Summarizing, custom search methods (findBy*) never return a projection. Unless you annotate the repository with #RepositoryRestResource(excerptProjection = BookingDetails.class), but this leads to some problems, first of all the client has to always use the same projection. How can we allow the user to use projections also with findBy* methods?
I verfied this working with Spring Data REST 2.2.1, so please update it. Make sure your client actually sends the the requested parameters as you intend. While debugging, I found out that e.g. cURL drops query parameters if you do not explicitly quote the URI. So this:
curl http://localhost:8080/orders/search/findByApplicant?applicant=5&projection=details
will not send any of the query parameters. Once you quote the URI, it will.
curl 'http://localhost:8080/orders/search/findByApplicant?applicant=5&projection=details'
Sort of the same is in place for the increasingly popular HTTPie. With it the required syntax is:
http :8080/orders/search/findByApplicant applicant==5 projection==details
In case you can't get it to work that way, it would be cool to get a running example project to look at.

Submitting / binding partial objects with spring mvc

The Spring MVC binding mechanism is powerful, but I'm now confronted with a trivial issue that I wonder how to resolve:
User JPA entity, that is used for the binding and validation as well (i.e. throughout all layers)
"Edit profile" page, that is not supposed to change the password or some other entity properties
Two ways that I can think of:
Using the same object
use #InitBinder to configure a list of disallowed properties
obtain the target user (by id)
then use a reflection utility (BeanUtils) to copy the submitted object to the target object, but ignore null values - i.e. fields that are not submitted
Introduce a new object that has the needed subset of fields, and use BeanUtils.copyProperties(..) to merge it to the entity.
Alternatives?
I've found that as soon as your web model starts to diverge from your business layer in function, it's best to use a view layer object (a model object) to collect, or display the data
the entity:
public class com.myapp.domain.UserEntity {
}
the model object:
public class com.myapp.somesite.web.SomeSiteUserModel {
public static SomeSiteUserModel from(UserEntity userEntity) {
... initialize model ...
}
public UserEntity getModelObject() {
... get entity back ...
}
}
now all view based operations can hand off processing to the internal model object if that makes sense, otherwise it can customize them itself. Of course the problem with this is you have to re-write all the getters and setters you want for the entity (an issue that I've had to deal with, that is annoying) unfortunately that is a bit of a Java language issue
I just checked up with two of the last Spring projects I have worked on and in both places the following approach is taken:
In the JSP page for the form the change password field has a name that does not match the name of the password field in the User bean, so that it doesn't get mapped to the bean. Then in the onSubmit method there is a separate check whether a new password has been submitted, and if it has been, the change is reflected explicitly.
Поздрави,
Vassil
You can read the object from the database first and bind then the request. You can find an example at FuWeSta-Sample.
It uses a helper-bean which must be initialized by Spring.

Categories