Create a entity mapper with cyclic dependencies - java

I've a problem with a project i'm working on. I need to create a mapper that convert an entity object to it's VO (Value Object) form, i need to do that to limit dependencies between my persistence layer and my business layer but i've some cyclic dependencies that i can't resolve, look at this example :
I want to use a Competence object in my business layer so i use the mapper to convert the entity into a VO that is usable by my layer.
class Competence {
private Domain dom;
}
class Domain {
private List<Competence> lComp;
}
But when i convert a Competence object, i need to convert a Domain too and when i convert a Domain i need to convert the Competence list etc etc... And i don't really want to convert half of my database :/
I've thinking about converting half of the object or avoid some object to stop the cycle but it's dangerous and this is not really a solution for my problem :/
Haved you a solution to solve this ?
Thanks in advance ! :)

One standard mechanism to deal with this kind of problem is to recode to something like:
class Competence {
}
class Domain {
}
class CompetenceDomain {
Competence competence;
Domain domain;
}
Map<Domain,List<Competence>> domainsWithCompetence = ...;
Map<Competence,Domain> competencesInDomain = ...;
This breaks the relationships of the objects out from the objects themselves into a separate mechanism.

There are a couple of ways around this. First, you have to decide which side you want to convert. Let's assume you want to convert Competences and not convert Domains.
Use an ID to reference the Domain inside the Competence.
Use a stub Domain object that only contains the ID and a minimal set of fields (not including Competences) that you need.
Hopefully I've correctly understood your question.

Related

Generic - call actual methods of object passed in parameter

There are around 6 POJO classes (domain entities, DTO's, DMO's) all have almost same fields. To convert from one objec to another, I'm passing one object and calling its getters to set it in another object.
private UserTemp convertDmoToUserTempEntity(final UserDmo userDmo) {
final UserTemp userTemp = new UserTemp();
userTemp.setUsername(userDmo.getUsername());
userTemp.setPassword(userDmo.getPassword());
userTemp.setStatus(userDmo.getStatus());
return userTemp;
}
private UserDmo convertEntityToUserDmo(final UserTemp userTemp) {
final UserDmo userDmo = new UserDmo();
userDmo.setUserId(userTemp.getUserId());
userDmo.setUsername(userTemp.getUsername());
userDmo.setStatus(userTemp.getStatus());
return userDmo;
}
There are lots of these conversion like from one entity to another, DTO to DMO, DMO To DTO etc. I believe the better way to handle this would be Generics, passing source object and destination object.
public static <E, T> T convert(E e, T t) {
//call getter of source object to set it in destination object.
return t;
}
UserConverterImpl.convertFromTempToUser(userTemp, user);
I need help in this. When I pass object in parameter, I need a way its methods. Is there any better way to achieve this?
You could try to use a framework for this. In the past I have used Dozer to do this.
In following post, other frameworks are mentioned as well
any tool for java object to object mapping?.
(some advice: When mapping JPA entity objects, watch out for lazy fields being automatically mapped by the frameworks)
Perhaps you don't want/cannot use a separate framework for whatever reason.
Since you seem to have a strict layering, you will probably have mappers for each layer. Then I would go for a separate mapping for each object. This way you can easily work out mapping from username to userId etc. The chances that all objects in the layers have exactly the same names for their methods are not that high, and likely to change anyway.
Ended up using BeanUtils of Spring.
BeanUtils.copyProperties(Object source, Object target)

is there a way to configure paritally or fully serializion to json using jersey?

I want to serialize a java object using jersey.
I want to serialize it and print it to file.
It's a big object and i want to save it twice:
one in a short version with mandatory fields only.
second in full version with all fields.
Is there a way to do so, other than create two DTOs
and duplicate the small object from the big object and then serialize them both to json?
To make it fast, Jersey help making REST webservices and Jackson help to manage a JSON Object.
So you can use both and have more ways to play with your objects.
Extending the JsonSerializer you could provide 2 custom serializer with the behaviour you want. I don't repost the link i put in comment, but there's an example in it.
Just to be sure, for me a non flat object is an object with private attributes that are business object to. If it is, yes, you could serialize a non flat object.
To serialize non flat objects, in my opinion there are two ways. And i based my development on the link i provided in comments (Item, User, Main class...).
First one, the composed one are simple so i could use something like this :
jgen.writeStartObject();
jgen.writeNumberField("id", value.id);
jgen.writeStringField("itemName", value.itemName);
jgen.writeObjectFieldStart("owner");
jgen.writeNumberField("id", value.owner.id);
jgen.writeStringField("name", value.owner.name);
jgen.writeEndObject();
jgen.writeEndObject();
In this case, the owner is composed with two fields, pretty simple.
The second solution is to use one another serializer :
One for main object, one for the composite and use :
jgen.writeObjectField("owner.", value.owner);
and don't forget to add the composed object serializer with :
module.addSerializer(User.class, new UserSerializer());
hope this help

Correct way of finding what was modified by a post in an spring-mvc controller?

It is a rather general question, but I will give a stripped down example. Say I have a Web CRUD application that manages simple entities stored in a database, nothing but classic : JSP view, RequestMapping annotated controller, transactional service layer and DAO.
On an update, I need to know the previous values of my fields, because a business rule asks a for a test involving the old and new values.
So I am searching for a best practice on that use case.
I thing that spring code is way more extensively tested and more robust than my own, and I would like to do it the spring way as much as possible.
Here is what I have tried :
1/ load an empty object in controller and manage the update in service :
Data.java:
class Data {
int id; // primary key
String name;
// ... other fields, getters, and setters omitted for brevity
}
DataController
...
#RequestMapping("/data/edit/{id}", method=RequestMethod.GET)
public String edit(#PathVariable("id") int id, Model model) {
model.setAttribute("data", service.getData(id);
return "/data/edit";
}
#RequestMapping("/data/edit/{id}", method=RequestMethod.POST)
public String update(#PathVariable("id") int id, #ModelAttribute Data data, BindingResult result) {
// binding result tests omitted ..
service.update(id, data)
return "redirect:/data/show";
}
DataService
#Transactional
public void update(int id, Data form) {
Data data = dataDao.find(id);
// ok I have old values in data and new values in form -> do tests stuff ...
// and MANUALLY copy fields from form to data
data.setName(form.getName);
...
}
It works fine, but in real case, if I have many domain objects and many fields in each, it is quite easy to forget one ... when spring WebDataBinder has done it including validation in the controller without I have to write any single thing other than #ModelAttribute !
2/ I tried to preload the Data from the database by declaring a Converter
DataConverter
public class DataConverter<String, Data> {
Data convert(String strid) {
return dataService.getId(Integer.valueOf(strid));
}
}
Absolutely magic ! The data if fully initialized from database and fields present in form are properly updated. But ... no way to get the previous values ...
So my question is : what could be the way to use spring DataBinder magic and to have access to previous values of my domain objects ?
You have already found the possible choices so i will just add some ideas here ;)
I will start with your option of using a empty bean and copying the values over to a loaded instance:
As you have shown in your example it's an easy approach. It's quite easily adaptable to create a generalized solution.
You do not need to copy the properties manually! Take a look at the 'BeanWrapperImpl' class. This spring object allows you to copy properties and is in fact the one used by Spring itself to achieve it's magic. It's used by the 'ParameterResolvers' for example.
So copying properties is the easy part. Clone the loaded object, fill the loaded object and compare them somehow.
If you have one service or just several this is the way to go.
In my case we needed this feature on each entity. Using Hibernate we have the issue that an entity might not only change inside a specific service call, but theoretically all over the place..
So I decided to create a 'MappedSuperClass' which all entities need to extend. This entity has a 'PostLoad' event listener which clones the entity in a transient field directly after loading. (This works if you don't have to load thousands of entities in a request.) Then you need also the 'PostPersist' and 'PostUpdate' listeners to clone the new state again as you probably don't reload the entity before another modification.
To facilitate the controller mapping I have implemented a 'StringToEntityConverter' doing exactly what you did, just generalized to support any entity type.
Finding the changes in a generalized approach will involve quite a bit of reflection. It's not that hard and I don't have the code available right now, but you can also use the 'BeanWrapper' for that:
Create a wrapper for both objects. Get all 'PropertyDescriptors' and compare the results. The hardest part is to find out when to stop. Compare only the first level or do you need deep comparison?
One other solution could also be to rely on Hibernate Envers. This would work if you do not need the changes during the same transaction. As Envers tracks the changes during a flush and creates a 'Revision' you can "simply" fetch twp revisions and compare them.
In all scenarios you will have to write a comparison code. I'm not aware of a library but probably there is something around in the java world :)
Hope that helps a bit.

How to add java custom or string object to DAO model object at runtime?

I need to add new String object to Array of custom type object, ServiceOrderEntity in this case. I know that this kind of breaks ServiceOrderEntity integrity but I have to access this field from jsp. What is the best way to do it?
DAO class:
...
SQLQuery localSQLQuery = localSession.createSQLQuery(query).addEntity(ServiceOrderEntity.class);
localList = localSQLQuery.list();
Iterator itr = localList.iterator();
while (itr.hasNext()){
String field = "some value";
itr.next().append( field ); // something like that maybe....
}
return to Service class
...
Service class
...
List list = perform DAO request
model.addAttribute("serviceOrderList", localList);
....
UPDATE
I have all models generated by Hibernate and I don't want to touch them. I need to add to custom object, in this case ServiceOrderEntity or find workaround. I think I can make copy of it and append new field to it (using Dozer)? New fields is result of other complex subqueries.
List of ServiceOrderEntity objects at runtime:
-list
--[0]model.ServiceOrderEntity#d826d3c7
---createdBy = {....}
---serviceRequestFK{java.Lang.Integer} // << this one
--[1]
....
etc
I need to get name using serviceRequestFK in ServiceOrderEntity. As long as java doesn't allow hot fix (to add custom filed to already created object) I need to find a way to pass to JSP the name field as well. What is the right way?
I really don't want to include DAO mathod requests from jsp...
Create separate list of names?...
Since Java does not allow mix-ins (aka monkey-patching) you'll have to:
Add the field to the base entity.
Return a sub-class that includes this field.
If you'd like to add the field so that the Service class can do its job, then fair enough. However, if the new field is part of the payload in/out then consider instead for that particular service then consider:
Making use-case specific payloads for each service call.
Map the results of these onto your reusable object model. (You can use something like Dozer for this).
The rationale behind this suggestion is to follow the principles of contract-first development.
Your model will be more general purpose, and thus reusable. You can add reusable behaviors to your model classes. Your services will use these behaviors to orchestrate process. (As opposed to having 'anaemic' entitites).
Your service payloads can remain relatively stable over time. So changes to your model won't effect all of your service subscribers. (aka "don't spill your guts").

design of building DTO from domain object

I have a graph of domain objects and i need to build a DTO to send it to the view. How to design it properly? I see 2 options where can I put the DTO building code:
1) Into the DTO constructor. But then the domain object has to present all fields to DTO via getters so it's not a DDD.
public DTO(DomainObject domain) {
/// access internal fields of different domain object.
}
2) Into the domain object. There will be no problem with accessing fields but the domain object will grow very fast when new view are added.
public DTO1 createDTO1() {
...
}
public DTO2 createDTO1() {
...
}
// and so on...
How should I build DTOs properly?
I think there is a bigger issue at play here. You should not be querying your domain. Your domain should be focused on behaviour and, as such, will quite possibly not contain the data in a format suitable for a view, especially for display purposes.
If you are sending back your entire, say, Customer object to Edit then you are performing entity-based interactions that are very much data focused. You may want to try and place more attention on task-based interactions.
So to get data to your view I'd suggest a simple query layer. Quite often you will need some denormalized data to improve query performance and that will not be present in your domain anyway. If you do need DTOs then map them directly from your data source. If you can get away with a more generic data container structure then that is first prize.
Variants:
Constructor with simple types in DTO: public DTO(Long id, String title, int year, double price)
Separate class - converter with methods like: DTO1 createDTO1(DomainObject domain)
Framework for copy properties from one object to other, like Dozer: http://dozer.sourceforge.net/
1) ... the domain object has to present all fields to DTO via getters ...
2) ... the domain object will grow very fast ...
As you can see, the problem is that both alternatives are coupling your model with your DTOs, so you need to decouple them: introduce a layer between them in charge of performing the mapping/translation.
You may find this SO question useful.
domain object has to present all fields to DTO via getters so it's not
a DDD
Just because a domain object has getters doesn't make it anemic or anti-DDD. You can have getters and behavior.
Besides, since you want to publish to the View a DTO containing particular data, I can't see how this data can remain private inside the domain object. You have to expose it somehow.
Solution 2) breaks separation of concerns and layering (it's not a domain object's business to create a DTO) so I'd stick with 1) or one of #pasha701's alternatives.

Categories