Hi
I like the “name pattern” functionality and use it in comboboxes to represent an entity.
@NamePattern("%s (_PS)|identifier")
My questions:
- Can the instance name also be used in tables?
- How is it done?
Thanks
Oliver
Hi
I like the “name pattern” functionality and use it in comboboxes to represent an entity.
@NamePattern("%s (_PS)|identifier")
My questions:
Thanks
Oliver
try MetadataTools.getInstanceName()
Generally if you use the base name of the entity, that shows the instanceName. So if you have an entity named customer, having a field or column’s property set to simply customer, that will show the instance name.
Ah but then again on a table column you can’t do it that way.
I would define a Transient Field that returns the value of instanceName and then put said transient field as the table column.
@Transient
@MetaProperty
public String getInsName() {
return getInstanceName();
}
As @jon.craig suggested, you can define a non-persistent property on the entity, but better use MetadataTools
directly because the getInstanceName()
method of the entity is deprecated in 7.2 and will be removed in the future:
@Transient
@MetaProperty(related = "identifier")
public String getInstName() {
return AppBeans.get(MetadataTools.class).getInstanceName(this);
}
The related
element ensures that the listed persistent attributes will be fetched if you define the transient attribute in a view.
Another way is to define a generator for a table column in the screen descriptor:
<groupTable id="customersTable" dataContainer="customersDc">
<columns>
<!-- -->
<column id="instName2"/>
</columns>
public class CustomerBrowse extends StandardLookup<Customer> {
@Inject
private MetadataTools metadataTools;
@Install(to = "customersTable.instName2", subject = "columnGenerator")
private Component customersTableInstName2ColumnGenerator(Customer customer) {
return new Table.PlainTextCell(metadataTools.getInstanceName(customer));
}
Studio can create this @Install
method for you if you put the cursor on the column XML element and double-click in the columnGenerator method on the Handlers tab of the Component Inspector.
Regards,
Konstantin
Thank you all for your help.
I was trying to implement the solution with the transient property on the entity. Unfortunately, it did not work as expected. My guess is that it does some how not work with our inheritance definition.
The relevant inheritance “branch” is like this:
DataProductStruct (DP) <|— SingleActor (SA) <|— FacadeLayer (FL)
Inheritance strategies:
First, I was putting the method into DataProductStruct, as “identifier” is defined on DataProductStruct. Then I put the method into SingleActor, as shown in the code below.
With all variants of the code, I always get the same error…
@NamePattern("%s (_SA)|identifier")
@DiscriminatorColumn(name = "DTYPE", discriminatorType = DiscriminatorType.STRING)
@Inheritance(strategy = InheritanceType.JOINED)
@Table(name = "SIMI_SINGLE_ACTOR")
@Entity(name = "simi_SingleActor")
public class SingleActor extends DataProductStruct {
private static final long serialVersionUID = 847162714173552240L;
@Transient
@MetaProperty(related = "identifier")
public String getFullIdentifier() {
return AppBeans.get(MetadataTools.class).getNamePatternProperties(this.getMetaClass()).toString();
//return AppBeans.get(MetadataTools.class).getInstanceName(this);
//return getInstanceName();
}
}
Error:
java.lang.IllegalArgumentException: Unable to find column identifier
at com.haulmont.cuba.web.gui.components.WebAbstractTable.sort(WebAbstractTable.java:814)
at ch.so.agi.simi.web.screens.singleactor.SingleActorBrowse.onAfterShow(SingleActorBrowse.java:58)
at com.haulmont.bali.events.EventHub.publish(EventHub.java:170)
at com.haulmont.cuba.gui.screen.Screen.fireEvent(Screen.java:128)
at com.haulmont.cuba.gui.screen.UiControllerUtils.fireEvent(UiControllerUtils.java:60)
at com.haulmont.cuba.web.sys.WebScreens.show(WebScreens.java:477)
at com.haulmont.cuba.web.sys.WebScreens.showFromNavigation(WebScreens.java:543)
at com.haulmont.cuba.gui.config.MenuItemCommands$ScreenCommand.run(MenuItemCommands.java:335)
at com.haulmont.cuba.web.sys.SideMenuBuilder$MenuCommandExecutor.accept(SideMenuBuilder.java:264)
at com.haulmont.cuba.web.sys.SideMenuBuilder$MenuCommandExecutor.accept(SideMenuBuilder.java:249)
at com.haulmont.cuba.web.gui.components.mainwindow.WebSideMenu$MenuItemImpl.menuSelected(WebSideMenu.java:573)
at com.haulmont.cuba.web.widgets.CubaSideMenu$1.menuItemTriggered(CubaSideMenu.java:90)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ...
I am currently running on cuba V 7.1.4
What do I need to do to resolve this?
Thanks
Oliver
I’m guessing you’re going to need to show the code of the three involved entity classes, then maybe it’ll become clear. It’s saying there’s no column named “identifier,” so… is there one?
Sure thing Jon - here we go
The column identifier “lives” in the mapped superclass DataProductStruct
DataProduct
package ch.so.agi.simi.entity;
import com.haulmont.chile.core.annotations.Composition;
import com.haulmont.chile.core.annotations.MetaProperty;
import com.haulmont.cuba.core.entity.StandardEntity;
import com.haulmont.cuba.core.entity.annotation.OnDelete;
import com.haulmont.cuba.core.global.AppBeans;
import com.haulmont.cuba.core.global.DeletePolicy;
import com.haulmont.cuba.core.global.MetadataTools;
import javax.persistence.*;
import javax.validation.constraints.NotNull;
import java.util.List;
@MappedSuperclass
public class DataProductStruct extends StandardEntity {
private static final long serialVersionUID = -6791785436085208832L;
@NotNull
@Column(name = "IDENTIFIER", nullable = false)
protected String identifier;
@Column(name = "TITLE")
protected String title;
@NotNull
@Column(name = "IN_WGC", nullable = false)
protected Boolean inWGC = false;
@Lob
@Column(name = "REMARKS")
protected String remarks;
public String getIdentifier() {
return identifier;
}
public void setIdentifier(String identifier) {
this.identifier = identifier;
}
public String getRemarks() {
return remarks;
}
public void setRemarks(String remarks) {
this.remarks = remarks;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public Boolean getInWGC() {
return inWGC;
}
public void setInWGC(Boolean inWGC) {
this.inWGC = inWGC;
}
}
SingleActor
package ch.so.agi.simi.entity;
import com.haulmont.chile.core.annotations.MetaProperty;
import com.haulmont.chile.core.annotations.NamePattern;
import com.haulmont.cuba.core.global.AppBeans;
import com.haulmont.cuba.core.global.MetadataTools;
import javax.persistence.*;
import javax.validation.constraints.NotNull;
@NamePattern("%s (_SA)|identifier")
@DiscriminatorColumn(name = "DTYPE", discriminatorType = DiscriminatorType.STRING)
@Inheritance(strategy = InheritanceType.JOINED)
@Table(name = "SIMI_SINGLE_ACTOR")
@Entity(name = "simi_SingleActor")
public class SingleActor extends DataProductStruct {
private static final long serialVersionUID = 847162714173552240L;
@Transient
@MetaProperty(related = "identifier")
public String getFullIdentifier() {
return AppBeans.get(MetadataTools.class).getNamePatternProperties(this.getMetaClass()).toString();
//return AppBeans.get(MetadataTools.class).getInstanceName(this);
//return getInstanceName();
}
}
FacadeLayer
package ch.so.agi.simi.entity;
import com.haulmont.chile.core.annotations.Composition;
import com.haulmont.chile.core.annotations.NamePattern;
import com.haulmont.cuba.core.entity.annotation.OnDelete;
import com.haulmont.cuba.core.global.DeletePolicy;
import javax.persistence.*;
import java.util.List;
@NamePattern("%s (FL)|identifier")
@PrimaryKeyJoinColumn(name = "ID", referencedColumnName = "ID")
@Table(name = "SIMI_FACADE_LAYER")
@Entity(name = "simi_FacadeLayer")
public class FacadeLayer extends SingleActor {
private static final long serialVersionUID = 7872122417388121333L;
@OrderBy("sort")
@Composition
@OnDelete(DeletePolicy.CASCADE)
@OneToMany(mappedBy = "facadelayer")
protected List<DatasetListProperties> dataSetListProperties;
public List<DatasetListProperties> getDataSetListProperties() {
return dataSetListProperties;
}
public void setDataSetListProperties(List<DatasetListProperties> dataSetListProperties) {
this.dataSetListProperties = dataSetListProperties;
}
}
Cheers
Oliver
Hmm; that all looks fine to me, other than your use of return AppBeans.get(MetadataTools.class).getNamePatternProperties(this.getMetaClass()).toString();
instead of the code Konstantin recommended (and you have also commented out).
What is happening when you get the exception you posted? Is it upon opening a screen, etc? (Looks like opening a screen from the stack trace.) How have you referenced the transient property in said screen? (If it’s a screen-open that’s causing the exception.)
Hi Jon
The “suspicious code” was my trying to find a workaround - the thrown error with the code from Konstantin is exactly the same.
And yes - the error happens when opening the browse screen. The transient property is referenced like this. I dont’t think that there is anything wrong with that - the framework is looking in the entity for “identifier” - as it should. Only that it fails somewhere.
@knstvk: Can you help us out on this one?
<groupTable id="singleActorsTable"
width="100%"
dataContainer="singleActorsDc">
<actions>
<action id="create" type="create"/>
<action id="edit" type="edit"/>
<action id="remove" type="remove"/>
</actions>
<columns>
<column id="fullIdentifier"/>
<column id="title"/>
<column id="inWGC"/>
<column id="remarks"/>
</columns>
<rowsCount/>
<buttonsPanel id="buttonsPanel"
alwaysVisible="true">
<button id="createPdsBtn" caption="Postgres-DS neu erstellen" stylename="primary"/>
<button id="createFlBtn" caption="FacadeLayer neu erstellen" stylename="friendly"/>
<button id="editBtn" action="singleActorsTable.edit" caption="Eintrag editieren" stylename="primary"/>
<button id="removeBtn" action="singleActorsTable.remove" caption="Eintrag löschen" stylename="danger"/>
</buttonsPanel>
</groupTable>
Which view does singleActorsDc
use? And is the fullIdentifier
in said view?
Hi Jon
I think now you are very close to crack the problem!
Currently configured is the “_local” view. From what I gather from this blog Views - the uncharted mystery – Road to CUBA and beyond... - it must be at least the “_minimal” view.
Do you know whether I should be fine with the _minimal view or if I need to define my own view? I can also just try it out…
And - due to corona, I will only be in office on my dev machine on tuesday - can not try out sooner…
Cheers
Oliver
_minimal
contains less than _local
so that’s not your answer. Local contains everything that’s … local … to the entity - that is, all its directly contained attributes. Minimal is just that - minimal.
Usually what I do (and the examples/tutorials/quickstart mostly show) is create an entity-browse-view
and/or entity-edit-view
with the things I need.
So you’d make a singleActor-browse-view
and include everything you need into that - including the transient field you need.
I have a strong feeling that will work.
(We don’t have any quarantines or anything here…yet. Hopefully we won’t. Take care!)
It works now.
The problem was - very humbling for me - the usage of the column “identifier” in a sort instruction in the controller. I replaced the column “identifier” with “fullIdentifier” and forgot to adapt the sort code…
@Subscribe
public void onAfterShow(AfterShowEvent event) {
singleActorsTable.sort("identifier", Table.SortDirection.ASCENDING);
}
Thank you all for your help!