Hi, forum followers and cuba support team.
When we’re trying to populate a non-persistent entity attribute with the listener BeforeDetachEntityListener the value is correctly assigned but the error “Cannot get unfetched attribute from detached object” on the entity-browser form appears although all attributes are included on the corresponding view. But, if the sentence @Listeners(“UbicacioEntityListener”) in Entity definition is commented, the entity-browser form doesn’t produce this error and, of course, the transient attribute doesn’t have any value.
We have checked that entity-browser’s view include all necessary attributes, but we don’t resolve the problem.
We would be very grateful if someone could help us.
Error message:
Class with transient ‘saldo’ attribute:
package com.company.magatzem.entity;
import com.haulmont.chile.core.annotations.MetaProperty;
import com.haulmont.chile.core.annotations.NamePattern;
import com.haulmont.cuba.core.entity.StandardEntity;
import com.haulmont.cuba.core.entity.annotation.*;
import com.haulmont.cuba.core.global.DeletePolicy;
import javax.persistence.*;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
@PublishEntityChangedEvents
@NamePattern("%s|ubicacioId")
@Table(name = "MAGATZEM_UBICACIO")
@Entity(name = "magatzem_Ubicacio")
@Listeners("UbicacioEntityListener")
public class Ubicacio extends StandardEntity {
private static final long serialVersionUID = -4212919895910187491L;
@CaseConversion
@Pattern(message = "{msg://magatzem_Ubicacio.ubicacioId.validation.Pattern}", regexp = "[A-Z]{1}[0-9]{2}[0-9]{2}")
@NotBlank(message = "La ubicació no pot tenir espais en blanc")
@NotEmpty(message = "{msg://magatzem_Ubicacio.ubicacioId.validation.NotEmpty}")
@NotNull
@Column(name = "UBICACIO_ID", nullable = false, length = 8)
protected String ubicacioId;
@OnDelete(DeletePolicy.DENY)
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "DARRER_MOVIMENT_ID")
private MovimentUbicacio darrerMoviment;
@Column(name = "COMENTARI")
protected String comentari;
@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "MAGATZEM_ID")
protected Magatzem magatzem;
@OnDeleteInverse(DeletePolicy.DENY)
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "PARTIDA_ID")
protected Partida partida;
@Transient
@MetaProperty(related = {"partida"})
private Integer saldo;
public Integer getSaldo() {
return saldo;
}
public void setSaldo(Integer saldo) { this.saldo = saldo;}
public MovimentUbicacio getDarrerMoviment() {
return darrerMoviment;
}
public void setDarrerMoviment(MovimentUbicacio darrerMoviment) {
this.darrerMoviment = darrerMoviment;
}
public Partida getPartida() {
return partida;
}
public void setPartida(Partida partida) {
this.partida = partida;
}
public String getComentari() {
return comentari;
}
public void setComentari(String comentari) {
this.comentari = comentari;
}
public Magatzem getMagatzem() {
return magatzem;
}
public void setMagatzem(Magatzem magatzem) {
this.magatzem = magatzem;
}
public String getUbicacioId() {
return ubicacioId;
}
public void setUbicacioId(String ubicacioId) {
this.ubicacioId = ubicacioId;
}
}
EntityListener with BeforeDetachEntityListener:
package com.company.magatzem.listeners;
import com.company.magatzem.service.UbicacioService;
import org.springframework.stereotype.Component;
import com.haulmont.cuba.core.listener.*;
import javax.inject.Inject;
import com.haulmont.cuba.core.EntityManager;
import com.company.magatzem.entity.Ubicacio;
@Component("UbicacioEntityListener")
public class UbicacioEntityListener implements BeforeDetachEntityListener<Ubicacio> {
@Inject
private UbicacioService ubicacioService;
@Override
public void onBeforeDetach(Ubicacio ubicacio, EntityManager entityManager){
ubicacio.setSaldo(ubicacioService.getSaldoUnitats(ubicacio, ubicacio.getPartida()));
}
}
Entity-browser form that produces "“Cannot get unfetched attribute[comentari] from detached object” error:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<window xmlns="http://schemas.haulmont.com/cuba/screen/window.xsd"
xmlns:c="http://schemas.haulmont.com/cuba/screen/jpql_condition.xsd"
caption="msg://browseCaption"
focusComponent="ubicaciosTable"
messagesPack="com.company.magatzem.web.screens.ubicacio">
<data readOnly="true">
<collection id="ubicaciosDc"
class="com.company.magatzem.entity.Ubicacio"
view="ubicacio-selector">
<loader id="ubicaciosDl">
<query>
<![CDATA[select e from magatzem_Ubicacio e]]>
</query>
</loader>
</collection>
</data>
<dialogMode height="600"
width="800"/>
<layout expand="ubicaciosTable"
spacing="true">
<filter id="filter"
applyTo="ubicaciosTable"
dataLoader="ubicaciosDl">
<properties include=".*"/>
</filter>
<groupTable id="ubicaciosTable"
width="100%"
dataContainer="ubicaciosDc">
<actions>
<action id="create" type="create"/>
<action id="edit" type="edit"/>
<action id="remove" type="remove"/>
</actions>
<columns>
<column id="ubicacioId">
<formatter class="com.company.magatzem.web.UbicacioFormata"/>
</column>
<column id="comentari"/>
<column id="magatzem"/>
<column id="saldo"/>
</columns>
<rowsCount/>
<buttonsPanel id="buttonsPanel"
alwaysVisible="true">
<button id="createBtn" action="ubicaciosTable.create"/>
<button id="editBtn" action="ubicaciosTable.edit"/>
<button id="removeBtn" action="ubicaciosTable.remove"/>
</buttonsPanel>
</groupTable>
<hbox id="lookupActions" spacing="true" visible="false">
<button action="lookupSelectAction"/>
<button action="lookupCancelAction"/>
</hbox>
</layout>
</window>
Affected view “ubicacio-selector”:
<view entity="magatzem_Ubicacio" name="ubicacio-selector" systemProperties="true">
<property name="saldo"/>
<property name="magatzem" view="_minimal" fetch="AUTO"/>
<property name="partida" view="_minimal" fetch="AUTO"/>
<property name="ubicacioId"/>
<property name="comentari"/>
</view>
Our development platform is:
- CUBA Platform version: 7.2.19
- CUBA Studio plugin version: 15.9-202
- IntelliJ version: CUBA Studio 2020.2