(Spring) How to force jpa to update with If-Match "*"? - spring

I have an (put) endpoint in some micro service lets call it A which can call from outside of the domain and from another micro service inside the same domain.
I implemented if-match header with #Version annotation and working just fine but i need additional feature such as; they want to call this endpoint from another micro service at the same domain with "*" and i have to tell JPA to accept request without optimistic-locking.
How could i force JPA to update if the request come from same domain with "*"?

Ok i just fixed this. We were using JPA totaly wrong when updating entity. When update some entity you should just get this entity from repo and set its fields. For example;
FooData comes service layer from controller and FooEntity comes from repo. You should use FooData to just check fields of FooEntity and set null to (#Version) tagged row_version. This means jpa can automaticaly increase number and worked well to me.
Wrong Behaviour: Convert FooData into BarEntity type-> Set new values to BarEntity and repository save the new entity.
If i'm still doing wrong please update me, I'll be appreciated.

Related

How to update Auto generated time stamp in Spring boot

I am making use of Auditing with Spring Data JPA to automatically update the created by time stamp. I have a requirement, where i have to migrate some data for which the created by date should be updated with the value am setting through the application. I have debugged the code, the values are setting properly. But while calling
fooRepository.save(fooEntity)
The created by is getting overridden by the auto generated time stamp.
Is it possible to override the value?
I am also having a #Transactional annotation in Service level. While debugging i can see the date is getting replaced on the Entity returned by the save repository method.
It is not a better way but you can follow.
First, create the entity
fooRepository.saveAndFlush(fooEntity);
and then update the createdAt data then save the entity again.
fooEntity.setCreatedAt(yourTime);
fooRepository.saveAndFlush(fooEntity);
Create new enity without #CreatedDate and new repository for that new entity.
Only use that new repository when you need to edit CreatedDate or LastModifiedDate
This seems to be a bad solution but is the only solution I can think of now.
I am looking for better solution to this problem

Spring Data Rest PUT v.s PATCH LinkableResources

I'm using Spring Data REST to expose my Entity's and their relationships. I have a OneToOne relationship between two Entity's and I'm trying to update/change the relationship with PUT and PATCH.
I noticed that Spring Data REST will only allow you to update linked resources - JPA mapped Entity's (OneToMany, ManyToOne, etc) which are also AggregateRoots (has a Repository) - via a PATCH and are ignored with a PUT.
This can be seen in the LinkedAssociationSkippingAssociationHandler class:
if (associationLinks.isLinkableAssociation(association)) {
return;
}
Why is this? What is the reasoning behind this?
Is it because the design wants us to treat the associations as resources themselves as seen in this part of the documentation? I can alter the relationship via a PUT with Content-Type text/uri-list but it feels unnatural and require an additional HTTP request.
From the Spring data REST 2.5.9.RELEASE the associations are not update on PUT request and only update using PATCH.
Changes in version 2.5.9.RELEASE (2017-04-19)
DATAREST-1030 - PATCH requests do not handle links to associations properly.
Other links about this:
DATAREST-1061: PUT-request with application/json media type payload cannot update association #OneToOne by URI
Domain Driven Design and Spring

Struts 2 tomcat request/session contamination

I am using Struts 2 v 2.3.16.3 with tomcat 6.
A user will click on an action which finds an object by id and the page displays it. I have encountered a sporadic bug where the user will all of a sudden get the id of another lookup from another user on another machine. So effectively they are both calling the same action but passing different id to the request, but both end up viewing the same id.
This is obviously disastrous, and the data is totally corrupted as both users think they are editing a different record. Any ideas how make sure session/request activity is kept secure to each session?
I am also using spring and am using the #Transactional annotation in my Service layer, which returns the objects from the DAO. Is there something I need to do with this annotation to make it secure for each session ?
I am using org.springframework.orm.hibernate3.HibernateTransactionManager
Classic Thread-UnSafe problem.
Since you nominated Spring, my first guess is that you have not specified the right scope for your action beans in Spring xml configuration.
Be sure you are using scope="prototype" because otherwise the default scope of Spring is Singleton, and you don't want a single(ton) instance of an Action, that would not be ThreadLocal (and hence ThreadSafe) anymore.
If it is not that, it could be something on an Interceptor (that, differently from an action, is not Thread Safe), or you are using something static (in your Business / DAO layer, or in the Action itself) that should be not.

Spring annotation based configuration change

I have a spring MVC (3.1) web app using Hibernate that is all working correctly - today, I have tried to move the configuration completely over to annotation based config (only using xml for the security stuff that isnt yet supported by Spring in code config).
After some tuning I got the app starting with no errors and the home page loads correctly - however I am seeing some different behaviour with the Hibernate sessions - namely, I am getting the following error when loading a page that actually touches Hibernate entities:
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.tmm.web.domain.Profile.connections, no session or session was closed
This is happening in the following scenario:
a request hits my #Controller and it loads the user Profile object
In the same method call (so we are not talking detached entities etc here) it tries to call profile.getConnections()
Profile.connections do not actually explicitly state a fetchtype, so should default to eager load (is my understanding?), but either way, the getConnections() call is directly after the loading of the profile - so would have thought even if it was being loaded lazily, it could easily just go back to the DB and load connections on demand.
//#Controller Code
Account viewedUser = accountService.loadAccountByUserName(userName);
model.put("viewedUserConnections", viewedUser.getUserProfile().getConnections());
//Profile Entity
#OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
private List connections = new ArrayList();
Now, I know about lazy loading etc, so it's not a question about that - like i mentioned all the Hibernate stuff was working correctly - so really my question is, what Spring configuration might affect this behaviour?
I can post my before and after xml vs annotation config, but am hoping that someone can point me in the direction of some config that I might have missed in switching.
Your assumptions are mainly wrong:
In the same method call (so we are not talking detached entities etc here)
The method is a method of the controller. In typical Spring applications, controllers are not transactional, but services are. So, unless you configured an "open session in view" filter or interceptor, the session is closed when the transactional service method returns, and the controller thus always uses detached entities
Profile.connections do not actually explicitly state a fetchtype, so should default to eager load
No. XxxToMany associations are lazy by default.
If the same code worked before the transition, my guess is that you had an open session in view filter or interceptor, and that you forgot it when migrating to annotations.

Auditing JPA entities in webapp : how to obtain logged-in user?

I have a simple auditing requirement for my JPA entities : keep the creation and last modification date and author. The author should be the currently logged-in user.
I would like to implement this using #PrePersist and #PreUpdate annotations on a base class, or a JPA interceptor (no additional framework).
However, in both cases, I need a way to access the currently logged in user, which is stored in the HttpSession.
How can I access this information from a method on my base entity class or from a JPA interceptor ?
Is there any best practice or any tested method on how to achieve that ?
I was thinking, maybe add a web interceptor that, for each request, puts the logged-in user object into a globally reachable ThreadLocal (e.g. inside a Spring singleton service), which would make it possible to look it up from anywhere...
Does that sound like a good idea ?
Any suggestion welcome !
Edit: found similar question here (found it only after posting my own through suggestions on the right) : Setting createdBy and updatedBy in JPA entities automatically
The conclusion seems to go in the direction of ThreadLocal... still, any feedback welcome !
If you do not use remote (EJB) calls then the idea to use ThreadLocal should work, as most containers use one thread for each request processed. You need to be careful when you put the user and when you delete it, as the container probably uses a thread pool and you don't want to leave the user object attached to a thread that might be used to process another request.

Resources