Passing complex JPA Entities to the controller with POJO - java

My team is coding an application that involves editing wikipedia-like pages.
It is similar to the problem we have with registration:
A straightforward implementation gives something like
public static void doRegistration(User user) {
//...
}
The user parameter is a JPA Entity. The User model looks something like this:
#Entity
public class User extends Model {
//some other irrelevant fields
#OneToMany(cascade = CascadeType.ALL)
public Collection<Query> queries;
#OneToMany(cascade = CascadeType.ALL)
public Collection<Activity> activities;
//...
I have read here and there that this fails. Now, in Play!, what is the best course of action we can take? There must be some way to put all that data that has to go to the server in one object, that easily can be saved into the database.
EDIT: The reason this fails is because of the validation fail. It somehow says "incorrect value" when validating collection objects. I was wondering if this can be avoided.
SOLUTION: Changing the Collection to List has resolved the issue. This is a bug that will be fixed in play 1.2 :)
Thanks beforehand

this works. To be more clear, you can define a controller method like the one you wrote:
public static void doRegistration(User user) {
//...
}
That's completely fine. Just map it to a POST route and use a #{form} to submit the object, like:
#{form id:'myId', action:#Application.doRegistration()}
#{field user.id}
[...]
#{/form}
This works. You may have problems if you don't add all the field of the entity in the form (if some fields are not editable, either use hidden inputs or a NoBinding annotation as described here).
EDIT: on the OneToMany subject, the relation will be managed by the "Many" side. That side has to keep the id of the related entity as a hidden field (with a value of object.user.id). This will solve all related issues.

It doesn't fail. If you have a running transaction, the whole thing will be persisted. Just note that transactions are usually running within services, not controllers, so you should pass it from the controller to the service.

Related

DDD implementation with Spring Data and JPA + Hibernate problem with identities

So I'm trying for the first time in a not so complex project to implement Domain Driven Design by separating all my code into application, domain, infrastructure and interfaces packages.
I also went with the whole separation of the JPA Entities to Domain models that will hold my business logic as rich models and used the Builder pattern to instantiate. This approach created me a headache and can't figure out if Im doing it all wrong when using JPA + ORM and Spring Data with DDD.
Process explanation
The application is a Rest API consumer (without any user interaction) that process daily through Scheduler tasks a fairly big amount of data resources and stores or updates into MySQL. Im using RestTemplate to fetch and convert the JSON responses into Domain objects and from there Im applying any business logic within the Domain itself e.g. validation, events, etc
From what I have read the aggregate root object should have an identity in their whole lifecycle and should be unique. I have used the id of the rest API object because is already something that I use to identify and track in my business domain. I have also created a property for the Technical id so when I convert Entities to Domain objects it can hold a reference for the update process.
When I need to persist the Domain to the data source (MySQL) for the first time Im converting them into Entity objects and I persist them using the save() method. So far so good.
Now when I need to update those records in the data source I first fetch them as a List of Employees from data source, convert Entity objects to Domain objects and then I fetch the list of Employees from the rest API as Domain models. Up until now I have two lists of the same Domain object types as List<Employee>. I'm iterating them using Streams and checking if an objects are not equal() between them if yes a collection of List items is created as a third list with Employee objects that need to be updated. Here I've already passed the technical Id to the domain objects in the third list of Employees so Hibernate can identify and use to update the records that are already exists.
Up to here are all fairly simple stuff until I use the saveAll() method to update the records.
Questions
I alway see Hibernate using INSERT instead of updating the list of
records. So If Im correct Hibernate session is not recognising the
objects that Im throwing into it because I have detached them when I
used the convert to domain object?
Does anyone have a better idea how can I implement this differently or fix
this problem?
Or should I stop using this approach as two different objects and continue use
them as rich Entity models?
Simple classes to explain it with code
EmployeeDO.java
#Entity
#Table(name = "employees")
public class EmployeeDO implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
public EmployeeDO() {}
...omitted getter/setters
}
Employee.java
public class Employee {
private Long persistId;
private Long employeeId;
private String name;
private Employee() {}
...omitted getters and Builder
}
EmployeeConverter.java
public class EmployeeConverter {
public static EmployeeDO serialize(Employee employee) {
EmployeeDO target = new EmployeeDO();
if (employee.getPersistId() != null) {
target.setId(employee.getPersistId());
}
target.setName(employee.getName());
return target;
}
public static Employee deserialize(EmployeeDO employee) {
return new Country.Builder(employee.getEmployeeId)
.withPersistId(employee.getId()) //<-- Technical ID setter
.withName(employee.getName())
.build();
}
}
EmployeeRepository.java
#Component
public class EmployeeReporistoryImpl implements EmployeeRepository {
#Autowired
EmployeeJpaRepository db;
#Override
public List<Employee> findAll() {
return db.findAll().stream()
.map(employee -> EmployeeConverter.deserialize(employee))
.collect(Collectors.toList());
}
#Override
public void saveAll(List<Employee> employees) {
db.saveAll(employees.stream()
.map(employee -> EmployeeConverter.serialize(employee))
.collect(Collectors.toList()));
}
}
EmployeeJpaRepository.java
#Repository
public interface EmployeeJpaRepository extends JpaRepository<EmployeeDO, Long> {
}
I use the same approach on my project: two different models for the domain and the persistence.
First, I would suggest you to don't use the converter approach but use the Memento pattern. Your domain entity exports a memento object and it could be restored from the same object. Yes, the domain has 2 functions that aren't related to the domain (they exist just to supply a non-functional requirement), but, on the other side, you avoid to expose functions, getters and constructors that the domain business logic never use.
For the part about the persistence, I don't use JPA exactly for this reason: you have to write a lot of code to reload, update and persist the entities correctly. I write directly SQL code: I can write and test it fast, and once it works I'm sure that it does what I want. With the Memento object I can have directly what I will use in the insert/update query, and I avoid myself a lot of headaches about the JPA of handling complex tables structures.
Anyway, if you want to use JPA, the only solution is to:
load the persistence entities and transform them into domain entities
update the domain entities according to the changes that you have to do in your domain
save the domain entities, that means:
reload the persistence entities
change, or create if there're new ones, them with the changes that you get from the updated domain entities
save the persistence entities
I've tried a mixed solution, where the domain entities are extended by the persistence ones (a bit complex to do). A lot of care should be took to avoid that domain model should adapts to the restrictions of JPA that come from the persistence model.
Here there's an interesting reading about the splitting of the two models.
Finally, my suggestion is to think how complex the domain is and use the simplest solution for the problem:
is it big and with a lot of complex behaviours? Is expected that it will grow up in a big one? Use two models, domain and persistence, and manage the persistence directly with SQL It avoids a lot of caos in the read/update/save phase.
is it simple? Then, first, should I use the DDD approach? If really yes, I would let the JPA annotations to split inside the domain. Yes, it's not pure DDD, but we live in the real world and the time to do something simple in the pure way should not be some orders of magnitude bigger that the the time I need to to it with some compromises. And, on the other side, I can write all this stuff in an XML in the infrastructure layer, avoiding to clutter the domain with it. As it's done in the spring DDD sample here.
When you want to update an existing object, you first have to load it through entityManager.find() and apply the changes on that object or use entityManager.merge since you are working with detached entities.
Anyway, modelling rich domain models based on JPA is the perfect use case for Blaze-Persistence Entity Views.
Blaze-Persistence is a query builder on top of JPA which supports many of the advanced DBMS features on top of the JPA model. I created Entity Views on top of it to allow easy mapping between JPA models and custom interface defined models, something like Spring Data Projections on steroids. The idea is that you define your target structure the way you like and map attributes(getters) via JPQL expressions to the entity model. Since the attribute name is used as default mapping, you mostly don't need explicit mappings as 80% of the use cases is to have DTOs that are a subset of the entity model.
The interesting point here is that entity views can also be updatable and support automatic translation back to the entity/DB model.
A mapping for your model could look as simple as the following
#EntityView(EmployeeDO.class)
#UpdatableEntityView
interface Employee {
#IdMapping("persistId")
Long getId();
Long getEmployeeId();
String getName();
void setName(String name);
}
Querying is a matter of applying the entity view to a query, the simplest being just a query by id.
Employee dto = entityViewManager.find(entityManager, Employee.class, id);
The Spring Data integration allows you to use it almost like Spring Data Projections: https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features and it can also be saved back. Here a sample repository
#Repository
interface EmployeeRepository {
Employee findOne(Long id);
void save(Employee e);
}
It will only fetch the mappings that you tell it to fetch and also only update the state that you make updatable through setters.
With the Jackson integration you can deserialize your payload onto a loaded entity view or you can avoid loading alltogether and use the Spring MVC integration to capture just the state that was transferred and flush that. This could look like the following:
#RequestMapping(path = "/employee/{id}", method = RequestMethod.PUT, consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<String> updateEmp(#EntityViewId("id") #RequestBody Employee emp) {
employeeRepository.save(emp);
return ResponseEntity.ok(emp.getId().toString());
}
Here you can see an example project: https://github.com/Blazebit/blaze-persistence/tree/master/examples/spring-data-webmvc

In Spring Data is it possible to delete entities using an entity's unique attribute?

Is it possible to delete entities using an entity's unique attribute?
In Spring Data 1.4.3.RELEASE, adding methods to find by unique attributes is very easy but, I haven't found a way to do it with delete.
In the following code, Spring automagically handles the findByAddress, is there something similar for delete?
Something like void deleteByAddress(String hwAddress);, I have added it to TerminalRepository but it doesn't work.
public Terminal {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private long id;
#Column(unique=true)
private String hwAddress;
...
}
public interface TerminalRepository extends
CrudRepository<Terminal, Long> {
Terminal findByAddress(String hwAddress);
}
Of course it is possible to find the entity by address and then use the delete(Terminal) method passing the found entity as parameter. But this wouldn't be good in terms of performance as it will be making one unnecessary call to the database database, i.e., one avoidable call to find the object and another one to delete it
I don't think there's anything built-in for that. You'd have to use the custom method support to roll your own:
http://docs.spring.io/spring-data/jpa/docs/1.4.3.RELEASE/reference/html/repositories.html#repositories.custom-implementations
I was facing the same issue. But, when I annotated method in repository interface with #Modifying , it started working. But, I don't know how it started working. Can anybody explain?

Hibernate/JPA version concurrency control and DTO/change command patterns

I would like to use #Version for optimistic concurrency control with JPA & Hibernate.
I know how it works in the typical scenario of two parallel transactions. I also know that if I have a CRUD with 1:1 mapping between the form and entity, I can just pass version along as a hidden field and use this to prevent concurrent modifications by users.
What about more interesting cases, which use DTOs or change command patterns? Is it possible to use #Version in this scenario as well, and how?
Let me give you an example.
#Entity
public class MyEntity {
#Id private int id;
#Version private int version;
private String someField;
private String someOtherField;
// ...
}
Now let's say two users open the GUI for this, make some modifications and save changes (not at the same time, so the transactions don't overlap).
If I pass the entire entity around, the second transaction will fail:
#Transactional
public void updateMyEntity(MyEntity newState) {
entityManager.merge(newState);
}
That's good, but I don't like the idea of passing entities everywhere and sometimes would use DTOs, change commands etc.
For simplicity change command is a map, eventually used in a call like this on some service:
#Transactional
public void updateMyEntity(int entityId, int version, Map<String, Object> changes) {
MyEntity instance = loadEntity(entityId);
for(String field : changes.keySey()) {
setWithReflection(instance, field, changes.get(field));
}
// version is unused - can I use it somehow?
}
Obviously, if two users open my GUI, both make a change, and execute it one after another, in this case both changes will be applied, and the last one will "win". I would like this scenario to detect concurrent modification as well (the second user should get an exception).
How can I achieve it?
If I understand your question correctly, all you need is a setter for your private int version field and when you update the entity, you set it in your entity. Of course your DTO must always transport version data. Eventually, you would do also something like:
MyEntity instance = loadEntity(entityId);
entityManager.detach(instance);
for(String field : changes.keySey()) {
setWithReflection(instance, field, changes.get(field));
}
//set also the version field, if the loop above does not set it
entityManager.merge(instance);

Objectify + JSP: displaying 1:N relationships

My bean looks like that:
#Entity
public class Fattura {
#Id
Long id;
#NotEmpty
String numero;
#Min(value=0)
Double importo;
Key<User> utente;
// gets & sets....
}
The "utente" property is the key of another bean I created: a "Fattura" can have only one "User", one "User" can have many "Fattura"s
My Spring MVC controller will manage a request for a list of Fattura and display them in a simple jsp:
#RequestMapping( value = "/fatture" , method = RequestMethod.GET )
public ModelAndView leFatture() {
ModelAndView mav = new ModelAndView("fatture");
mav.addObject("fatture",fatturaService.listFatture());
return mav;
}
the code of the jsp is really simple: only a foreach cycle in a table
My question is:
how can I display the "utente"?
The only thing I have is its key, but I'd like to do something like ${fattura.utente.firstName} in my JSP, how can I do it?
Unfortunately you would have to manually fetch "utente" in your DAO class. There is no automatic fetching in Objectify like in Twig. In my POJOs I have following fields
#Transient private Organization sender; // Pickup location (for client RPC)
transient private Key<Organization> senderKey; // Pickup location (for Datastore)
I load entity from Datastore and then load manually Organization using senderKey.
In new Objectify4 you'll be able to do what you want like this:
class Beastie {
#Parent
#Load
ParentThing parent;
#Id Long id;
#Load({"bigGroup", "smallGroup"})
SomeThing some;
#Load("bigGroup")
List<OtherThing> others;
#Load
Ref<OtherThing> refToOtherThing;
Ref<OtherThing> anotherRef; // this one is never fetched automatically
}
Here is evolving design document of new version.
Update at Nov 17, 2011: This is big news. Twig author, John Patterson, joined Objectify project today.
I know it sounds annoying that you have to manually fetch the two objects, but it's actually very useful to know that you're doubling your work and time to do this - each "get" call take a while and the second won't start until the first is complete. It a typical NoSQL environment, you shouldn't often need to have two separate entities - is there a reason that you do?
There are only two reasons I can easily think of:
The class references another object of the same type - this is the example in the Objectify documentation, where a person has a reference to their spouse, who is also a person.
The class that you're embedding the other into ("Fattura" in your case) has masses of data in it that you don't want fetched at the same time as you want to fetch the "User" - and you need the user on it's own more often than you need the "Fattura" and the "User". It would need to be quite a lot of data to be worth the extra datastore call when you DO want the "Fattura".
You don't necessarily have to use temporary field for just getting a object.
This works:
public User getUtente() {
Objectify ofy = ObjectifyService.begin();
return ofy.get(utenteKey);
}
This will of course do a datastore get() each time the getter is called. You can improve this by using #Cached on your User entity, so they turn into memcache calls after the first call. Memcache is good, but we can do a little better using the session cache:
public User getUtente() {
Objectify ofy = myOfyProvider.get();
return ofy.get(utenteKey);
}
The key thing here is that you need to provide (through myOfyProvider) an instance of Objectify that is bound to the current request/thread, and that has the session cache enabled. (ie, for any given request, myOfyProvider.get() should return the same instance of Objectify)
In this setup, the exact same instance of User will be returned from the session cache each time the getter is called, and no requests to the datastore/memcache will be made after from the initial load of this Entity.

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