Symfony 2 Validate Proxy Entity - validation

So I have an entity with annotation asserts and I call validate() manually on the entity, everything works as expected.
However sometimes a process before this hydrates the same entity through a relationship. Then later when I fetch the entity normally I get a proxy of that entity (which is initialised), I believe Doctrine does this automatically for performance reasons.
However when I then come to validate it, because the class is a proxy the annotation asserts don't get picked up.
Should validate() know how to validate a proxy by loading the asserts from it's base class it proxies from? I assume not since it isn't.
So my question is, is there any way to turn a proxy entity into it's normal entity class (I don't mean hydrate/initialise it because it already is).
Or is there a way to force Doctrine to re-fetch the entity from the database and not return me an initialised proxy?

Ah-ha I had to call $em->clear() after requesting the related entity to make sure I got a none-proxy entity the next time round.

Related

If Service returns DTO not entity, how to handle DTO in other service in Spring Boot?

After reading this article, I change return value of service method entity into DTO.
But I'm little confused in this below situation.
Entity A <- Repository A <- Service A
Entity B <- Repository B <- Service B
Then , If Service B need to access entity A ,so call method in Service A. Since the result of that method is DTO ,not entity, I'm having a hard time dealing with DTO A in Service B.
Should I call repository A in Service B? or should I call Service A in Service B and use modelmapper to covert dto to entity in service B?
// Controller code
#RestController
public FooDTO getSomeFoo(){
return new FooDTO(service.getFoo())
}
// Service code
#Service
public Foo getFoo(){
return repository.find(~)
}
In my opinion, unless you really want to protect your entities to be changed elsewhere other than the corresponding Service, I would avoid DTOs in calls inside the service layer. This means that it is ok to return Entities in methods that you know that are called by other Services in your application, unless you really want to, most probably, over-engineer your application.
Having said that you should return DTOs only in the methods that are called by your Controller layer so that they are used in your REST API (assuming you have one).
Of course, this requires discipline and making sure you don't call methods on your Controller that are supposed to be called only by Services. There is an architecture that tries to tackle this (if you want to read more about it --> https://medium.com/#shivendraodean/software-architecture-the-onion-architecture-1b235bec1dec) and you can try to take advantage of package protected feature to guarantee this.
Should I call repository A in Service B?
Definitely not. You should never (never may be a strong word, but you should at least strive hard to avoid it) do this, otherwise your code will turn into a complete mess without any structure whatsoever.

Spring Data problem - derived delete doesn't work

I have a spring boot application (based off spring-boot-starter-data-jpa. I have an absolute minimum of configuration going on, and only a single table and entity.
I'm using CrudRepository<Long, MyEntity> with a couple of findBy methods which all work. And I have a derived deleteBy method - which doesn't work. The signature is simply:
public interface MyEntityRepository<Long, MyEntity> extends CrudRespository<> {
Long deleteBySystemId(String systemId);
// findBy methods left out
}
The entity is simple, too:
#Entity #Table(name="MyEntityTable")
public class MyEntity {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="MyEntityPID")
private Long MyEntityPID;
#Column(name="SystemId")
private String systemId;
#Column(name="PersonIdentifier")
private String personIdentifier;
// Getters and setters here, also hashCode & equals.
}
The reason the deleteBy method isn't working is because it seems to only issue a "select" statement to the database, which selects all the MyEntity rows which has a SystemId with the value I specify. Using my mysql global log I have captured the actual, physical sql and issued it manually on the database, and verified that it returns a large number of rows.
So Spring, or rather Hibernate, is trying to select the rows it has to delete, but it never actually issues a DELETE FROM statement.
According to a note on Baeldung this select statement is normal, in the sense that Hibernate will first select all rows that it intends to delete, then issue delete statements for each of them.
Does anyone know why this derived deleteBy method would not be working? I have #TransactionManagementEnabled on my #Configuration, and the method calling is #Transactional. The mysql log shows that spring sets autocommit=0 so it seems like transactions are properly enabled.
I have worked around this issue by manually annotating the derived delete method this way:
public interface MyEntityRepository<Long, MyEntity> extends CrudRespository<> {
#Modifying
#Query("DELETE FROM MyEntity m where m.systemId=:systemId")
Long deleteBySystemId(#Param("systemId") String systemId);
// findBy methods left out
}
This works. Including transactions. But this just shouldn't have to be, I shouldn't need to add that Query annotation.
Here is a person who has the exact same problem as I do. However the Spring developers were quick to wash their hands and write it off as a Hibernate problem so no solution or explanation to be found there.
Oh, for reference I'm using Spring Boot 2.2.9.
tl;dr
It's all in the reference documentation. That's the way JPA works. (Me rubbing hands washing.)
Details
The two methods do two different things: Long deleteBySystemId(String systemId); loads the entity by the given constraints and ends up issuing EntityManager.delete(…) which the persistence provider is about to delay until transaction commits. I.e. code following that call is not guaranteed that the changes have already been synced to the database. That in turn is due to JPA allowing its implementations to actually do just that. Unfortunately that's nothing Spring Data can fix on top of that. (More rubbing, more washing, plus a bit of soap.)
The reference documentation justifies that behavior with the need for the EntityManager (again a JPA abstraction, not something Spring Data has anything to do with) to trigger lifecycle events like #PreDelete etc. which users expect to fire.
The second method declaring a modifying query manually is declaring a query to be executed in the database, which means that entity lifecycles do not fire as the entities do not get materialized upfront.
However the Spring developers were quick to wash their hands and write it off as a Hibernate problem so no solution or explanation to be found there.
There's detailed explanation why it works the way it works in the comments to the ticket. There are solutions provided even. Workarounds and suggestions to bring this up with the part of the stack that has control over this behavior. (Shuts faucet, reaches for a towel.)

How to avoid the vulnerability created by using entities at a requestMapping method?

I have a controller with a method like
#PostMapping(value="/{reader}")
public String addToReadingList(#PathVariable("reader") String reader, Book book) {
book.setReader(reader);
readingListRepository.save(book);
return "redirect:/readingList/{reader}";
}
When I run a static code analysis with Sonarqube I get a vulnerability report stating that
Replace this persistent entity with a simple POJO or DTO object
But if I use a DTO (which has exactly the same fields as the entity class, then I get another error:
1 duplicated blocks of code must be removed
What should be the right solution?
Thanks in advance.
Enric
You should build a new separate class which represents your Entity ("Book" ) as Plain Old Java Object (POJO) or Data Transfer Object (DTO). If you use JSF or other stateful technology this rule is important. If your entity is stateful there might be open JPA sessions etc. which may modify your database (e.g. if you call a setter in JSF on a stateful bean).
For my projects I ignore this Sonar rule because of two reasons:
I alway you REST and REST will map my Java Class into JSON which can be seen as a DTO.
REST is stateless (no server session) so no database transaction will be open after the transformation to JSON
Information obtained from sonarsource official documentation.
On one side, Spring MVC automatically bind request parameters to beans
declared as arguments of methods annotated with #RequestMapping.
Because of this automatic binding feature, it’s possible to feed some
unexpected fields on the arguments of the #RequestMapping annotated
methods.
On the other end, persistent objects (#Entity or #Document) are linked
to the underlying database and updated automatically by a persistence
framework, such as Hibernate, JPA or Spring Data MongoDB.
These two facts combined together can lead to malicious attack: if a
persistent object is used as an argument of a method annotated with
#RequestMapping, it’s possible from a specially crafted user input, to
change the content of unexpected fields into the database.
For this reason, using #Entity or #Document objects as arguments of
methods annotated with #RequestMapping should be avoided.
In addition to #RequestMapping, this rule also considers the
annotations introduced in Spring Framework 4.3: #GetMapping,
#PostMapping, #PutMapping, #DeleteMapping, #PatchMapping.
See More Here

Spring state machine's JpaRepositoryState and JPA's #Entity

We are considering using Spring State Machine for the following use case:
One of our entities (i.e. a JPA entity from our domain model) can be in one of a number of states and we have millions such entities (and as many lines in our database).
We are considering using:
org.springframework.statemachine.data.jpa.JpaStateRepository
Should we annotate our domain model classes with JpaRepositoryState and thereby create a dependency between our domain model and spring state machine?
What would be an alternative to the above i.e. ensure that our JPA entity class is not too tightly coupled to JpaRepositoryState?
What is the mapping/relationship between the state machine's machineId and the JPA entity's #Id?
JpaRepositoryState really doesn't have anything to do with your domain model as it is our entity class to store machine configuration in an external repository. Specifically it is a state representation and similarly there are entity classes for transitions, actions and guards.
There's no relationship between #id and machineId. #id is just a field identifying row in a database, which is autogenerated if you store entities manually via spring-data. Fields machineId and submachineId are however used together so that you're able to define multiple machines in a repository and then make a substate to reference a machine similarly how in UML you can define a plain state and then define that to be a reference to a submachine.
It seems that I'm getting more and more questions related user's entity classes and how to handle those with a statemachine, like in gh453. I don't really have an answer to this right now as Spring Statemachine was never designed to handle these specific use cases. This doesn't mean that Spring Statemachine would never handle these scenarious, we just don't have anything out of the box right now.
Also our documentation is lacking these topics which is a clear indication that we need to be better on that area.

Spring JPA force save

I have basic question but I cannot find the response for it.
As I see each time I change entity I have to save it.
But is there some way to enable autosave?
If the methods you update the entity is marked with #Transactional annotation, you don't need to call save or update methods.
Note that, the entity must be fetched from DB to be maintained. If the entity has already created, you still need to use save method.

Resources