Trying to understand datacontext.commit

Hi,

I’m following a couple of posts among the tutorials and documentation trying to understand why nothing is being commited to the DB.

Running CUBA 7.2.7 on Java 11 for this.

My sources are this demo project, the suggestion posted here and I read and checked what was suggested in this post about making data writable in screen descriptor and dataContext.commit().

I have browser editor screen pair. First the editor screen.

In the screen controller the snippet below isn’t working, as in nothing turns up in the database, then I click the button which invokes commitData(). This applies to either table or form component being tested.

public void commitData() {
        dataContext.commit();
    }

Now if I subscribe to, for example, the form it does work. Which is good but CUBA shows a warning about this in Studio.

@Subscribe("form")
public void commitData() {
        dataContext.commit();
    }

In the editor screen I use any attribute of type string for the sake of simplicity and understanding, let’s say name and ID field.

Now in the browse screen I try to reproduce a working implementation, as in the examples I linked above, to save the locale in a generated column then the button is clicked.

@Subscribe
    private void onInit(InitEvent event) {
        informationsTable.addGeneratedColumn("language", entity -> {
            LookupField<String> lookupField = uiComponents.create(LookupField.TYPE_STRING);
            List<String> locales = new ArrayList<>(globalConfig.getAvailableLocales().keySet());
            lookupField.setOptionsList(locales);
            lookupField.setWidth("100%");
            return lookupField;
        });
    }
    
    public void commitData() {
        dataContext.commit();
    }

Data is set to be writable and in the screen descriptor I add the button same as before

<button id="commitBtn" invoke="commitData" caption="Commit"/>

Yet in the browse screen nothing is commited to the database even if I @Subscribe.

I posted not long ago a question about commiting data in this post. For my question here I use the same demo project as in the other post extending it with the code posted based on the examples linked to.

What am I doing wrong? Why is the data being saved and not saved? Especially I would be highly interested on how to achieve saving the selection of a column added to a table using the addGeneratedColumn() method and of the selection of a RadioButtonGroup as asked in this post.

Thank you very much!

Hi,

Do you register your entities in the dataContext? Please read this topic, there was a long discussion about saving entities in the screens. Just let me know if it helps.

Thanks for the tip :slight_smile: I read the post and studied the demo project you attached. Then I changed in my test project the relevant parts.

@Subscribe("informationTable.commit")
    public void commitData(Action.ActionPerformedEvent event) {
        dataContext.commit();
    }

As well as changing how the button was used from invoke to @Subscribe.

Now I can edit values in browse screen as well as in the edit screen and commit to DB (ie. ID and name attribute which are strings).

What I do not yet can figure out is how to save the selection of the addGeneratedColumn() which I base on the documentation and demo.

Same goes saving which radio button was selected from the RadioButtonGroup.

Right now I am to understand DataManager but this is proofing difficult for me. For example I tried this construct to have the selection of radio buttons commited

public void commitData(Set<Questions> mapInfoToQuestion, List<Answers> mapInfoToAnswer) {
        Information information = metadata.create(Information.class);

        information.setMapInfoToQuestion(mapInfoToQuestion);
        information.setMapInfoToAnswer(mapInfoToAnswer);

        dataManager.commit(information);

Now I have no idea on how to actually trigger that it does its thing and I think the block isn’t complete yet either.

As I finally learned about zipProject I attached the current demo project test.zip (125.4 KB)

My goal would be to have either, better both, the generated column state commited proper to the DB as well as the state of which radio buttons were selected.

Please use dataContext.create() - it will register the entity in the screen’s data context.

Please note that the generated column cannot be saved because it is not mapped to an entity’s property. You probably need a column renderer in order to be able to save the value selected in the table. If it is what you want.

OK, I changed that and tried getting it to fly. Also following the forum and documentation, specifically this post and re-read about CollectionContainer.

Additionally I explored your suggestion with column renderer but ultimately decided to focus on one possible approach to the solution for now to reduce complexity and focus the learnings. Therefore the demo was trimmed down a bit test.zip (125.5 KB)

Edit screen controller now lists

 @Subscribe("windowCommitAndClose")
    public void commitData(Button.ClickEvent event) {
        Information information = dataContext.create(Information.class);
        informationsDc.getMutableItems().add(information);

//        information.setMapInfoToQuestion(mapInfoToQuestion);
//        information.setMapInfoToAnswer(mapInfoToAnswer);

        dataManager.commit(information);
        notifications.create(Notifications.NotificationType.HUMANIZED).withCaption("Triggered windowCommitAndClose").show();
    }

And the edit screen descriptor is smaller too

<data>
        <collection id="informationsDc"
                    class="com.company.test.entity.Information"
                    view="information-view">
            <loader id="informationsDl">
                <query>
                    <![CDATA[select e from test_Information e]]>
                </query>
            </loader>
        </collection>
        <collection id="questionsGroup1Dc" class="com.company.test.entity.reference.Questions" view="questions-view">
            <loader id="questionsGroup1Dl">
                <query>
                    <![CDATA[select e from test_Questions e]]>
                </query>
            </loader>
        </collection>
        <collection id="answersGroup1Dc" class="com.company.test.entity.reference.Answers" view="answers-view">
            <loader id="answersGroup1Dl">
                <query>
                    <![CDATA[select e from test_Answers e where e.mapAnswerToQuestion = :container_questionsGroup1Dc]]>
                </query>
            </loader>
        </collection>
        <instance id="informationDc" class="com.company.test.entity.Information" view="information-view">
            <loader id="informationDl"/>
            <collection id="questionsesDc" property="mapInfoToQuestion"/>
            <collection id="answeresDc" property="mapInfoToAnswer"/>
        </instance>
    </data>
    <dialogMode height="600"
                width="800"/>
    <facets>
        <dataLoadCoordinator auto="true"/>
    </facets>
    <layout spacing="true" margin="true">
        <vbox spacing="true" margin="true">
            <hbox id="editActions" spacing="true">
                <button id="windowCommitAndClose" action="windowCommitAndClose"/>
                <button action="windowClose"/>
            </hbox>
            <form id="informationForm" dataContainer="informationsDc">
                <column width="350px">
                    <groupBox spacing="true" collapsable="true"
                              showAsPanel="true">
                        <textField id="pismsIDField" property="pismsID"/>
                        <textField id="pismsNameField" property="pismsName"/>
                    </groupBox>
                    <groupBox spacing="true" caption="Question group 1" collapsable="true"
                              showAsPanel="true">
                        <radioButtonGroup id="questionGroup1" optionsContainer="questionsGroup1Dc"
                                          captionProperty="pismsName"
                                          dataContainer="informationsDc" property="selectedQuestion"/>
                        <radioButtonGroup id="answerGroup1" optionsContainer="answersGroup1Dc"
                                          captionProperty="pismsName"
                                          dataContainer="informationsDc" property="selectedAnswer"/>
                        <lookupField id="prodLnField" optionsContainer="answersGroup1Dc"
                                     captionProperty="pismsName"
                                     dataContainer="informationsDc" property="selectedAnswer"/>
                    </groupBox>
                </column>
            </form>
        </vbox>

I use the windowCommitAndClose action now, got rid of an additional button.

What I still do not understand is how to add to the dataContext the attributes I want to save setting them through the RadioButtonGroup.

The attributes in the demo are n-to-n, snippet from the entity

    @JoinTable(name = "TEST_QUESTIONS_INFORMATION_LINK",
            joinColumns = @JoinColumn(name = "INFORMATION_ID"),
            inverseJoinColumns = @JoinColumn(name = "QUESTIONS_ID"))
    @ManyToMany
    private Set<Questions> mapInfoToQuestion;

    @JoinTable(name = "TEST_ANSWERS_INFORMATION_LINK",
            joinColumns = @JoinColumn(name = "INFORMATION_ID"),
            inverseJoinColumns = @JoinColumn(name = "ANSWERS_ID"))
    @ManyToMany
    private List<Answers> mapInfoToAnswer;

    public void setMapInfoToQuestion(Set<Questions> mapInfoToQuestion) {
        this.mapInfoToQuestion = mapInfoToQuestion;
    }

    public Set<Questions> getMapInfoToQuestion() {
        return mapInfoToQuestion;
    }

    public List<Answers> getMapInfoToAnswer() {
        return mapInfoToAnswer;
    }

    public void setMapInfoToAnswer(List<Answers> mapInfoToAnswer) {
        this.mapInfoToAnswer = mapInfoToAnswer;
    }

Now for the screen controller I tried injecting like this but that lead to errors while other constructs did not work either.

    @Inject
    private Set<Questions> mapInfoToQuestion;

    information.setMapInfoToQuestion(mapInfoToQuestion);

A working example/demo project for this specific use case to learn from would be highly appreciated if that would be OK! :blush:

A simple example that will help you to understand custom column generators and inline data update using lookup fields and radio groups.

Questionnare.zip (96.2 KB)