5

I have a form that should be bind to a complex object that wrap a lot of children, every time before loading this form I have to initialize all children object in a method that only have a lot of new statements and calling a setter method, I have to repeat this scenario for a lot of forms and other complex objects

Is there a better strategy than the initializeEmployee method?

For example:

@Entity
public class Employee {
    Integer Id;
    Contract contract;
    Name name;
    List<Certificate> list;
    // getter and setters
}

@Entity
public class Contract {
    String telephoneNum;
    String email;
    Address address;
    // getter and setters
}

@Entity
public class Address {
    String streetName;
    String streetNum;
    String city;
}

public class Name {
    String fName;
    String mName;
    String lName;
    // getter and setters
}

// And another class for certificates

public initializeEmployee() {
    Employee emplyee = new Employee();

    Name name = new Name();
    employee.setName(name);

    Contract contract = new Contract();
    Address  address = new Address();
    contract.setAddress(address);
    employee.setContract(contract);

    // set all other employee inner objects, 
}

EDIT: According to below answers, it seems that there is no optimal answer. However, I could use the Entity constructor or a Factory Design Pattern.

But both solutions don't solve my other problem in initializing all fields strategy with Required and Optional fields.

For example: If I have Name as required (i.e. the Employee entity will not persisted if Name object attributes are empty, on the other side the Contract entity is an optional. and I cannot persist an empty Contract object to the database, so I have to make it null first before persistence, then reinitialize it after persistence like the following

// Set Contract to null if its attributes are empty
Contract contract = employee.getContract()
if(contract.getTelephoneNum().isEmpty && contract.getEmail().isEmpty() && contract.getAddress().isEmpty()){
    empolyee.setContract(null);
}

employeeDAO.persist(employee);
// reinitialize the object so it could binded if the the user edit the fields.
employee.setContract(new Contract());
fujy
  • 5,168
  • 5
  • 31
  • 50
  • 1
    I'm not really sure what the point of this is. Why is it better (or even desirable) to have an empty or default object initialized? – Mikkel Løkke Oct 10 '13 at 12:47
  • @MikkelLøkke Because Spring Webflow needs initialized object to bind its attributer, else it will raise null pointer exception. – fujy Oct 10 '13 at 15:23
  • 1
    @fujy what Mikkel wanted to say was, if empty Employee object is not desired, then you should not let the user instantiate it without giving all required fields. – deepakraut Oct 16 '13 at 11:47

4 Answers4

7

You can add constructors (it is their role after all) to your entities to instanciate these fields if having a null value has no meaning for your case.

Another way, if you don't like adding contructors, is to add a static factory method to instanciate your bean which will look like initializeEmployee() but with potential parameters and returning an Employee object. http://en.wikipedia.org/wiki/Factory_method_pattern

Similarly, you can instanciate your collections too, as there is probably no meaning for a null collection (but there is one for an empty collection).

You can add behaviour to your entities, don't be locked in Anemic Domain Model which is considered an anti-pattern by Martin Fowler http://www.martinfowler.com/bliki/AnemicDomainModel.html

EDIT

I see you are using dao.persist(entity): you are probably using JPA. If so, maybe it is best to not modify your object graph (on the front side) and add an EntityListener (in the persistence layer) for Employee: here is a link for Hibernate EntityListener (it is a JPA feature, so if you are using another framework don't worry) http://docs.jboss.org/hibernate/entitymanager/3.5/reference/en/html/listeners.html

With an EntityListener, you can add small "aop like" actions before persistence and after. This will allow you to not deal with null values on the domain and front layers and will ensure that every entity fits in any case (better validation).

In PrePersist: you'all add your code to check null values (possibly with custom methods "isEmpty()" on the domain classes) and nullify fields if needed. In PostPersist you add your new object.

zenbeni
  • 7,019
  • 3
  • 29
  • 60
  • First, Vote up. Second, your answer gave me a lot of information. However, it could not solve my problem directly. – fujy Oct 17 '13 at 23:45
  • I have updated the question, please if think you could add more, It will be very helpful. But anyway I have give the bounty to someone, and since you have the most up voted answer, then you have it. – fujy Oct 18 '13 at 05:39
  • If you are looking for not persisting "empty" objects (ie with empty fields) then it is better to ask the objects directly before: employee.isEmpty(). I'll add an example. – zenbeni Oct 18 '13 at 06:17
4

I couldn't get what you really need, but I think you could try this way:

@Entity
public class Employee {
    Integer Id;
    Contract contract = new Contract();
    Name name = new Name();
    List<Certificate> list;
    // getter and setters
}

@Entity
public class Contract {
    String telephoneNum;
    String email;
    Address address = new Address();
    // getter and setters
}
Timofey Gorshkov
  • 4,987
  • 6
  • 41
  • 66
2

I'm not sure it reduces the verbosity at all but since this is a UI issue, you could initialize the editable objects in your flow.xml and then put it all together in an Employee instance prior to saving to the DB.

<on-start>
    <evaluate expression="new foo.bar.Name()" result="flowScope.employeeName" />
    <evaluate expression="new foo.bar.Contract()" result="flowScope.contract" />
    <evaluate expression="new foo.bar.Address()" result="flowScope.address" />
</on-start>
lance-java
  • 25,497
  • 4
  • 59
  • 101
  • Up Vote, that's a good one. However it doesn't solve my problem. I have updated the question – fujy Oct 18 '13 at 05:37
1

Actually I would advise against using Hibernate Entities directly in GUI. In many cases (I assume in yours too, but I'm missing some details on your use-case) it is useful to use a Data Transfer Object pattern instead. You can create such DTO that is GUI specific, has only those fields that you need, and the structure is only as complex as needed.

After specific user action (like save e.g.) use those DTOs (on event handling) to create your Entities that will be persisted.

Unless your case is that just entering the GUI screen causes Entities creation, then I would recommend Factory pattern.

Also note that in many cases initialization of component objects that are making up the main object (Employee in your example) are better to be initialized in constructor of main object, eg. if you expect that Contract cannot be null - initialize it in constructor. The same for the list of Certificates and others.

Rafi
  • 369
  • 2
  • 5
  • I disagree, while introducing DTOs eliminates some of the problems you describe, it also means that you now have to maintain 2 version of each class, one for persistence and one for the front-end. Also, you'll need to maintain the code that converts from persistent to front-end and vice versa. Modern JSON serializer have many mechanism for including/excluding what fields are serialized, specifying custom transformers by data types or field names, some even have the concept of 'views' where your JSON can have various level of saturation. – SergeyB Oct 16 '13 at 21:45
  • Well, everything depends on custom needs. Usage of serializers with custom transformers (most of the time some parts of data model are not easily serializable) is still a kind of DTO, but less explicitly. – Rafi Oct 16 '13 at 22:56
  • I also disagree that this is maintaining of two versions of classes. Those are simply two different classes. One representing entity in data model and other representing user data input. Separating data model layer from GUI layer requires data transformation especially respecting particular GUI technology aspects. It is of secondary manner if it is done with JSON serializer or DTO assembler. – Rafi Oct 16 '13 at 23:00
  • @Rafi, sometimes it can make sense to use entities on the front side. For instance, with Flex or JavaFX with GraniteDS, you can use advanced features such as bean validation, caching and lazy-loading. The richer your client side will become, the more you will need domain modelling in it. And with DRY principle, using entities can be really powerful. Again, as you said it depends on your needs. If you really want loose-coupling, the DTO approach is the only way (but expensive, if you want a very rich client). – zenbeni Oct 17 '13 at 09:41
  • 2
    @zenbeni I agree with you, this is why I said that it depends on needs. For example I have a project in progress that has very tight schedule. Thanks to loose coupling with DTOs all layers are developed at the same time, as we had not time to wait with the GUI for Domain to be designed. GUI and data model were developed at the same time. The last step was to make transfers GUI<->Domain. As you said (as well as I did) this also depends on GUI technology used, because there are sometimes supporting features worth considering. This is engineering not a religion ;). – Rafi Oct 17 '13 at 09:58
  • @Rafi Say you add "someNewField" (step 1) property to your Hibernate entity that needs to be displayed on the front-end, how do you reflect that change in your DTO? You'd add getters and setters for that property (step 2) to your DTO and then have to update your mapper to include this property when copying from (step 3) the DTO and to the DTO (step 4). With JSON serializer include/exclude just do step 1 and steps 3 and 4 are combined into one, reducing the amount of work by 50%. That is what I mean by maintaining two version of the same class. Sample: .include("uuid") – SergeyB Oct 17 '13 at 16:53
  • @ike_love Yes, partially true. Partially because using DTO assemblers it is one line to add, and only to those that need it. But let us look at the other example. In your domain you have an employee who has 15 properties. One of them is boss (getBoss()) who is employee as well. Now, you are requested to create a GUI that shows list of names of employees and names of their bosses. How many useless operations you do (converting needless attributes) and how many useless data do you transfer with simple JSON serializer? Is it efficient? How much longer is your Hibernate session then mine? – Rafi Oct 17 '13 at 17:29
  • Most of the time cheap solutions are not most efficient, and most efficient are not cheap ;). – Rafi Oct 17 '13 at 17:32
  • 1
    And if you start customizing JSON serialization to serialize only properties that are needed, then you did DTO :), but without separate class. Minor difference. You still have customized transformation. – Rafi Oct 17 '13 at 17:36
  • Another disadventage of using directly serialized entities is following: Lets assume that you are required to prepare GUI that shows the size of the department run by the boss. The size is "small" when up to 10 employees, medium for up to 50 employees, big when more than 100 employees. What I would DTO? Prepare DTO with boss' name and an Enumeration SMALL, MEDIUM, BIG. What would you do? Transfer all employees for every boss, so the GUI developer could count them? – Rafi Oct 17 '13 at 17:40
  • @Rafi What are you talking about? The original question was how to deal with serializing complex hibernate object graphs for the front-end to use, not how to send a NUMBER! This discussion has gotten way off topic. JSON is made for serializing complex object and Java libraries like flexjson provide support for it without having to maintain two version of every class + a mapper. Writing custom code for it is reinventing the wheel. Read up on this if you want to learn more about modern JSON serialization: http://wiki.fasterxml.com/JacksonJsonViews – SergeyB Oct 17 '13 at 19:37
  • @ike_love The question was not about serializing but about initialization of many complex objects. – Rafi Oct 17 '13 at 20:10
  • @Rafi - exactly my point, how do your counter arguments relate to complex objects? Your main counter argument has to do with simple counts, not complex objects. My point is still the same, your solution of creating a DTO for hibernate backed entities (which already ARE DTOs by definition, they are objects used to transfer data) doubles the amount of POJO code and introduces the need to manually map data back and forth between the two version. – SergeyB Oct 17 '13 at 23:44
  • @ike_love Like I said in my answer - it depends on what GUI does and what are its features. – Rafi Oct 18 '13 at 08:24
  • BTW in most of my cases I use Hibernate to persist Domain Entities, that are rarely are simple DTOs, as I do not use Anemic Domain Model Pattern. Maybe this is why you see a code duplication in my answer. – Rafi Oct 18 '13 at 08:25