Edit two or more linked entities by single editor

There are 4 entities:

Person - contains personal info about an individual
Address - contains postal addresses of an individual and relates to Person as many2many
Phone - telephone numbers, linked to Person as many2many
Customer - contains attributes of a customer and again relates to Person as many2many

Objective:

Editor to be developed to meet following requirements. Editor should be able to create all described entities by entering all mandatory info to a single form. Also CustomerID sequence to be generated automatically. I.e. we want to have single form to add info about a customer instead of 4 different editors and switching between those.

To do it:

  1. I created joined datasources (presonDS - main editor datasource)

<dsContext>...
    <datasource id="personDs" class="com.company.myapp.entity.Person">
        <collectionDatasource id="addressesDs" property="addresses"/>
        <collectionDatasource id="phonesDs" property="phones"/>
        <collectionDatasource id="customerDs" property="customer"/>
    </datasource>
</dsContext>
  1. Initialized following entities from the editor’s controller:

public class CustomerEdit extends AbstractEditor<Customer> {
    @Inject
    private UniqueNumbersService customerSeq;
    private HashSet<Phone> phoneSet = new HashSet<Phone>();
    private HashSet<Address> addressSet = new HashSet<Address>();
    private HashSet<Customer> customerSet = new HashSet<Customer>();

    @Override
    public void init(Map<String, Object> params) {}

    protected void initNewItem(Person item) {
        Long customerID = customerSeq.getNextNumber("customerSeq"); Customer customer = new Customer();
        customer.setCustomerID(customerID); customerSet.add(customer); item.setCustomer(customerSet);
        Address address = new Address(); addressSet.add(address); item.setAddresses(addressSet);
        Phone phone = new Phone(); phoneSet.add(phone); item.setPhones(phoneSet);
    }
}

Finally I get all fields of all linked entities which do not work, except of Person. Any input to Person disappears when field gets unfocused. Obviously I cannot submit changes, because all the mandatory fields are empty.

How can I make it work? And what’s wrong with my approach?

The problem you get is caused by the absence of the selected instance of the embedded data source. Usually it’s being done by components like Table (components which operate with lists). In your case you don’t use components of that kind. Consequently you are supposed to do it manually:


public class PersonEdit extends AbstractEditor<Person> {
    @Inject
    private CollectionDatasource<Address, UUID> addressesDs;

    @Override
    protected void initNewItem(Person item) {
        Address address = new Address(); item.setAddresses(new HashSet<Address>()); item.getAddresses().add(address);
    }

    @Override
    protected void postInit() {
        addressesDs.setItem(getItem().getAddresses().iterator().next());
    }
}

Thank you for your fast reply! It works now!
Still one issue left, which is not explicitly coming from the initial question.
I develop the editor which is based on Customer entity editor. In this case I have the following structure of the entities relations:
Customer -> Person -> Address
Customer -> Person -> Phone
Adding new items doesn’t cause any problem, all the linked entities are being created fine. But when I try to edit existing item I get NullPointerException raised by postInit() method. From my understanding the cause of the problem is an instance of Person entity. This instance is joined to editable Customer instance. When I load it Adders and Phone fields always come empty.
I tried to create “full” view for Person entity and snap it to collectionDataSource personDs. But it didn’t work out.
Could you please advise?

You get empty fields because those fields are not included to the view you use for the object you edit.
In case when you have Customer -> Person -> Address structure you need all the hierarchy to be included to the view of the Customer entity.
Defining a view for an embedded data source is not a solution and doesn’t match the XSD schema, because embedded data sources do not download data itself, but give an access to the instances linked to a master entity.

More precisely, single data sources (i.e. main data source of an editor) also do not download data by themselves, but they provide an editor with the information of what view should be used to download the edited instance.